/* Return the image index of the given pointer, or -1 if not found. */ int osx_find_image( const void *p ) { unsigned long image_count = _dyld_image_count(); for( unsigned i = 0; i < image_count; i++ ) { const struct mach_header *header = _dyld_get_image_header(i); if( header == NULL ) continue; /* The load commands directly follow the mach_header. */ const struct load_command *cmd = (struct load_command *) &header[1]; for( unsigned j = 0; j < header->ncmds; j++ ) { /* We only care about mapped segments. */ if( cmd->cmd != LC_SEGMENT ) { cmd = next_load_command(cmd); continue; } const segment_command *scmd = (const segment_command *) cmd; const unsigned long bottom = scmd->vmaddr + _dyld_get_image_vmaddr_slide( i ); const unsigned long top = scmd->vmaddr + scmd->vmsize + _dyld_get_image_vmaddr_slide( i ); if ( (unsigned long) p >= bottom && (unsigned long) p < top ) return i; cmd = next_load_command(cmd); } } return -1; }
static const struct mach_header *FindOwnerOfPC(unsigned int pc) { unsigned int count,index,offset,cmdex; struct segment_command *seg; struct load_command *cmd; const struct mach_header*header; count = _dyld_image_count(); for (index = 0;index < count;index += 1) { header = _dyld_get_image_header(index); offset = _dyld_get_image_vmaddr_slide(index); cmd = (struct load_command*)((char*)header + sizeof(struct mach_header)); for (cmdex = 0;cmdex < header->ncmds;cmdex += 1,cmd = (struct load_command*)((char*)cmd + cmd->cmdsize)) { switch(cmd->cmd) { case LC_SEGMENT: seg = (struct segment_command*)cmd; if ((pc >= (seg->vmaddr + offset)) && (pc < (seg->vmaddr + offset + seg->vmsize))) return header; break; } } } return NULL; }
static gboolean find_image_address_and_slide (const gchar * image_name, gpointer * address, gpointer * slide) { gboolean name_is_absolute; guint count, idx; name_is_absolute = index (image_name, '/') != NULL; count = _dyld_image_count (); for (idx = 0; idx != count; idx++) { const gchar * name, * s; name = _dyld_get_image_name (idx); if (!name_is_absolute && (s = strrchr (name, '/')) != NULL) name = s + 1; if (strcmp (name, image_name) == 0) { *address = (gpointer) _dyld_get_image_header (idx); *slide = (gpointer) _dyld_get_image_vmaddr_slide (idx); return TRUE; } } return FALSE; }
static inline void *getTMCloneTable (const void *f, size_t *tmct_siz) { char *tmct_fixed, *tmct = NULL; unsigned int i, img_count; struct mach_header *mh; Dl_info info; if (! dladdr (f, &info) || info.dli_fbase == NULL) abort (); mh = (struct mach_header *) info.dli_fbase; tmct_fixed = GET_DATA_TMCT (mh, tmct_siz); *tmct_siz /= (sizeof (size_t) * 2); /* No tm_clone_table or no clones. */ if (tmct_fixed == NULL || *tmct_siz == 0) return NULL; img_count = _dyld_image_count(); for (i = 0; i < img_count && tmct == NULL; i++) { if (mh == _dyld_get_image_header(i)) tmct = tmct_fixed + (unsigned long)_dyld_get_image_vmaddr_slide(i); } return tmct; }
bool interpose() { const struct mach_header_native *mach_hdr; uint32_t i; for(i = 0; (mach_hdr = (void *) _dyld_get_image_header(i)); i++) { find_lazy(mach_hdr->ncmds, (void *) (mach_hdr + 1), _dyld_get_image_vmaddr_slide(i)); } return true; }
static inline void *get_real_address(void *addr) { if (!addr) return NULL; // We need to slide the section address to get a valid pointer // because ASLR will shift the image by a random offset return addr + _dyld_get_image_vmaddr_slide(BASE_IMAGE_INDEX); }
void bin_update_image(int entry, void *trampee_addr) { int i, j, k; int header_count = _dyld_image_count(); // Go through all the mach objects that are loaded into this process for (i=0; i < header_count; i++) { const struct mach_header *current_hdr = _dyld_get_image_header(i); // Modify any callsites residing inside the text segment set_text_segment(current_hdr, "__text"); text_segment += _dyld_get_image_vmaddr_slide(i); update_callqs(entry, trampee_addr); int lc_count = current_hdr->ncmds; // this as a char* because we need to step it forward by an arbitrary number of bytes const char *lc = ((const char*) current_hdr) + sizeof(struct mach_header_64); // Check all the load commands in the object to see if they are segment commands for (j = 0; j < lc_count; j++) { if (((struct load_command*)lc)->cmd == LC_SEGMENT_64) { const struct segment_command_64 *seg = (const struct segment_command_64 *) lc; const struct section_64 * sect = (const struct section_64*)(lc + sizeof(struct segment_command_64)); int section_count = (seg->cmdsize - sizeof(struct segment_command_64)) / sizeof(struct section_64); // Search the segment for a section containing dyld stub functions for (k=0; k < section_count; k++) { if (strncmp(sect->sectname, "__symbol_stub", 13) == 0) { set_text_segment((struct mach_header*)current_hdr, sect->sectname); text_segment += _dyld_get_image_vmaddr_slide(i); update_dyld_stubs(entry, trampee_addr); } sect++; } } lc += ((struct load_command*)lc)->cmdsize; } } }
EXPORT DWORD GetImageCount() { uint32_t imagecount; int i; imagecount = _dyld_image_count(); for (i=0; i < imagecount; i++) { printf("Image name: %s %x %x\n", _dyld_get_image_name(i), (uint32_t)_dyld_get_image_vmaddr_slide(i), (uint32_t)_dyld_get_image_header(i)); } return imagecount; }
init_(void) { struct import_t table[] = { { 0, "_dlsym" }, { 0, NULL } }; int rv = find_stubs((void *)_dyld_get_image_header(0), table); intptr_t slide = _dyld_get_image_vmaddr_slide(0); if (rv == 1 && table[0].a) { my_printf("hooked %lx %s\n", table[0].a, table[0].s); *(void **)(table[0].a + slide) = (void *)my_dlsym; } }
/* * find the memory address where the target was loaded to * this is due to full ASLR in Lion * we also use it for Snow Leopard to avoid opening the binary and parse the mach-o header */ int find_image(struct header_info *hi) { // get mach-o header of iTunes image (main binary is usually (always?) index 0) // XXX: this can be made error-proof by iterating all images and match iTunes const struct mach_header *mh = _dyld_get_image_header(0); intptr_t aslr_slide = _dyld_get_image_vmaddr_slide(0); DEBUG_MSG("Aslr slide is %p\n", (void*)aslr_slide); hi->mh = (const struct mach_header_64*)mh; hi->aslr_slide = aslr_slide; // compute iTunes image size uint64_t image_size = 0; if (mh->magic != MH_MAGIC_64) { return -1; } if (mh->ncmds == 0 || mh->sizeofcmds == 0) { ERROR_MSG("Invalid number of commands or size."); } struct load_command *load_cmd = NULL; char *load_cmd_addr = (char*)mh + sizeof(struct mach_header_64); for (uint32_t i = 0; i < mh->ncmds; i++) { load_cmd = (struct load_command*)load_cmd_addr; if (load_cmd->cmd == LC_SEGMENT_64) { struct segment_command_64 *seg_cmd = (struct segment_command_64*)load_cmd; image_size += seg_cmd->vmsize; } load_cmd_addr += load_cmd->cmdsize; } if (image_size != 0) { hi->image_size = image_size; return 0; } else { /* failure */ return -1; } }
const void* ksdl_getSymbolAddrInImage(uint32_t imageIdx, const char* symbolName) { const struct mach_header* header = _dyld_get_image_header(imageIdx); if(header == NULL) { return NULL; } const uintptr_t imageVMAddrSlide = (uintptr_t)_dyld_get_image_vmaddr_slide(imageIdx); const uintptr_t segmentBase = ksdl_segmentBaseOfImageIndex(imageIdx) + imageVMAddrSlide; if(segmentBase == 0) { return NULL; } uintptr_t cmdPtr = ksdl_firstCmdAfterHeader(header); if(cmdPtr == 0) { return NULL; } for(uint32_t iCmd = 0; iCmd < header->ncmds; iCmd++) { const struct load_command* loadCmd = (struct load_command*)cmdPtr; if(loadCmd->cmd == LC_SYMTAB) { const struct symtab_command* symtabCmd = (struct symtab_command*)cmdPtr; const STRUCT_NLIST* symbolTable = (STRUCT_NLIST*)(segmentBase + symtabCmd->symoff); const uintptr_t stringTable = segmentBase + symtabCmd->stroff; for(uint32_t iSym = 0; iSym < symtabCmd->nsyms; iSym++) { // If n_value is 0, the symbol refers to an external object. if(symbolTable[iSym].n_value != 0) { const char* sname = (char*)((intptr_t)stringTable + (intptr_t)symbolTable[iSym].n_un.n_strx); if(*sname == '_') { sname++; } if(strcmp(sname, symbolName) == 0) { return (void*)(symbolTable[iSym].n_value + imageVMAddrSlide); } } } } cmdPtr += loadCmd->cmdsize; } return NULL; }
int rebind_symbols(struct rebinding rebindings[], size_t rebindings_nel) { int retval = prepend_rebindings(&_rebindings_head, rebindings, rebindings_nel); if (retval < 0) { return retval; } // If this was the first call, register callback for image additions (which is also invoked for // existing images, otherwise, just run on existing images if (!_rebindings_head->next) { _dyld_register_func_for_add_image(_rebind_symbols_for_image); } else { uint32_t c = _dyld_image_count(); for (uint32_t i = 0; i < c; i++) { _rebind_symbols_for_image(_dyld_get_image_header(i), _dyld_get_image_vmaddr_slide(i)); } } return retval; }
uint32_t ksdl_imageIndexContainingAddress(const uintptr_t address) { const uint32_t imageCount = _dyld_image_count(); const struct mach_header* header = 0; for(uint32_t iImg = 0; iImg < imageCount; iImg++) { header = _dyld_get_image_header(iImg); if(header != NULL) { // Look for a segment command with this address within its range. uintptr_t addressWSlide = address - (uintptr_t)_dyld_get_image_vmaddr_slide(iImg); uintptr_t cmdPtr = ksdl_firstCmdAfterHeader(header); if(cmdPtr == 0) { continue; } for(uint32_t iCmd = 0; iCmd < header->ncmds; iCmd++) { const struct load_command* loadCmd = (struct load_command*)cmdPtr; if(loadCmd->cmd == LC_SEGMENT) { const struct segment_command* segCmd = (struct segment_command*)cmdPtr; if(addressWSlide >= segCmd->vmaddr && addressWSlide < segCmd->vmaddr + segCmd->vmsize) { return iImg; } } else if(loadCmd->cmd == LC_SEGMENT_64) { const struct segment_command_64* segCmd = (struct segment_command_64*)cmdPtr; if(addressWSlide >= segCmd->vmaddr && addressWSlide < segCmd->vmaddr + segCmd->vmsize) { return iImg; } } cmdPtr += loadCmd->cmdsize; } } } return UINT_MAX; }
/* * This routine returns the a pointer to the data for the named section in the * named segment if it exist in the named Framework. Also it returns the size * of the section data indirectly through the pointer size. Otherwise it * returns zero for the pointer and the size. The last component of the path * of the Framework is passed as FrameworkName. */ void * getsectdatafromFramework( const char *FrameworkName, const char *segname, const char *sectname, unsigned long *size) { uint32_t i, n; uintptr_t vmaddr_slide; #ifndef __LP64__ struct mach_header *mh; const struct section *s; #else /* defined(__LP64__) */ struct mach_header_64 *mh; const struct section_64 *s; #endif /* defined(__LP64__) */ char *name, *p; n = _dyld_image_count(); for(i = 0; i < n ; i++) { name = _dyld_get_image_name(i); p = strrchr(name, '/'); if(p != NULL && p[1] != '\0') name = p + 1; if(strcmp(name, FrameworkName) != 0) continue; mh = _dyld_get_image_header(i); vmaddr_slide = _dyld_get_image_vmaddr_slide(i); #ifndef __LP64__ s = getsectbynamefromheader(mh, segname, sectname); #else /* defined(__LP64__) */ s = getsectbynamefromheader_64(mh, segname, sectname); #endif /* defined(__LP64__) */ if(s == NULL) { *size = 0; return(NULL); } *size = s->size; return((void *)(s->addr + vmaddr_slide)); } *size = 0; return(NULL); }
static CFStringRef _CFBundleDYLDCopyLoadedImagePathForPointer(void *p) { CFStringRef result = NULL; #if USE_DYLD_PRIV const char *name = dyld_image_path_containing_address(p); if (name) result = CFStringCreateWithFileSystemRepresentation(kCFAllocatorSystemDefault, name); #else /* USE_DYLD_PRIV */ if (!result) { uint32_t i, j, n = _dyld_image_count(); Boolean foundIt = false; const char *name; #if TARGET_RT_64_BIT #define MACH_HEADER_TYPE struct mach_header_64 #define MACH_SEGMENT_CMD_TYPE struct segment_command_64 #define MACH_SEGMENT_FLAVOR LC_SEGMENT_64 #else #define MACH_HEADER_TYPE struct mach_header #define MACH_SEGMENT_CMD_TYPE struct segment_command #define MACH_SEGMENT_FLAVOR LC_SEGMENT #endif for (i = 0; !foundIt && i < n; i++) { const MACH_HEADER_TYPE *mh = (const MACH_HEADER_TYPE *)_dyld_get_image_header(i); uintptr_t addr = (uintptr_t)p - _dyld_get_image_vmaddr_slide(i); if (mh) { struct load_command *lc = (struct load_command *)((char *)mh + sizeof(MACH_HEADER_TYPE)); for (j = 0; !foundIt && j < mh->ncmds; j++, lc = (struct load_command *)((char *)lc + lc->cmdsize)) { if (MACH_SEGMENT_FLAVOR == lc->cmd && ((MACH_SEGMENT_CMD_TYPE *)lc)->vmaddr <= addr && addr < ((MACH_SEGMENT_CMD_TYPE *)lc)->vmaddr + ((MACH_SEGMENT_CMD_TYPE *)lc)->vmsize) { foundIt = true; name = _dyld_get_image_name(i); if (name) result = CFStringCreateWithFileSystemRepresentation(kCFAllocatorSystemDefault, name); } } } } #undef MACH_HEADER_TYPE #undef MACH_SEGMENT_CMD_TYPE #undef MACH_SEGMENT_FLAVOR } #endif /* USE_DYLD_PRIV */ #if LOG_BUNDLE_LOAD printf("dyld image path for pointer %p is %p\n", p, result); #endif /* LOG_BUNDLE_LOAD */ return result; }
void SDMDaodanDumpLibraryInfo(char *dumpPath, struct SDMSTLibrary *libTable) { char *filePath = calloc(0x1, sizeof(char)*(strlen(dumpPath)+0x1+0xd)); sprintf(filePath, "%sLibraries.txt",dumpPath); FILE *file = fopen(filePath, "w"); if (file) { SDMDaodanWriteHeaderInDumpFile("Linked Libraries\n",file); for (uint32_t i = 0x0; i < libTable->dependencyCount; i++) { char *path = (char *)(libTable->dependency[i].loadCmd + libTable->dependency[i].dyl.dylib.name.offset); uintptr_t slide; if (libTable->couldLoad) { slide = _dyld_get_image_vmaddr_slide(SDMGetIndexForLibraryPath(path)); char *slideAndPath = calloc(0x1, sizeof(char)*(strlen(path)+0x15)); sprintf(slideAndPath, "\t0x%016lx %s\n",slide,path); FWRITE_STRING_TO_FILE(slideAndPath, file); free(slideAndPath); } } fclose(file); } free(filePath); }
static uintptr_t libSystemSlide() { Dl_info info; if ( dladdr(&malloc, &info) == 0 ) { FAIL("all_image_infos-cache-slide: dladdr(&malloc, xx) failed"); exit(0); } const struct mach_header* mallocMh = (struct mach_header*)info.dli_fbase; if ( (mallocMh->flags & 0x80000000) == 0 ) { FAIL("all_image_infos-cache-slide: image containing _malloc not in shared cache"); exit(0); } int count = _dyld_image_count(); for(int i=0; i < count; ++i) { if ( mallocMh == _dyld_get_image_header(i) ) { return _dyld_get_image_vmaddr_slide(i); } } FAIL("all_image_infos-cache-slide: slide of image containing _malloc not found"); exit(0); }
void SDMDaodanDumpSymbolInfo(char *dumpPath, struct SDMSTLibrary *libTable) { char *filePath = calloc(0x1, sizeof(char)*(strlen(dumpPath)+0x1+0xb)); sprintf(filePath, "%sSymbols.txt",dumpPath); FILE *file = fopen(filePath, "w"); if (file) { SDMDaodanWriteHeaderInDumpFile("Symbol Table\n",file); for (uint32_t i = 0x0; i < libTable->symbolCount; i++) { char *symbolName = (char *)(libTable->table[i].name); char *nameAndOffset = calloc(0x1, sizeof(char)*(strlen(symbolName)+0x100)); uintptr_t slide; if (libTable->couldLoad) { slide = _dyld_get_image_vmaddr_slide(libTable->libInfo->imageNumber); } else { slide = (uintptr_t)(libTable->libInfo->mhOffset); } sprintf(nameAndOffset, "\t0x%016lx %s\n",((libTable->table[i].offset)-slide),symbolName); FWRITE_STRING_TO_FILE(nameAndOffset, file); free(nameAndOffset); } fclose(file); } free(filePath); }
static ssize_t MSMachONameList_(const void *stuff, struct MSSymbolData *list, size_t nreq) { // XXX: ok, this is just pathetic; API fail much? size_t slide(0); for (uint32_t image(0), images(_dyld_image_count()); image != images; ++image) if (_dyld_get_image_header(image) == stuff) { slide = _dyld_get_image_vmaddr_slide(image); goto fat; } return -1; fat: const uint8_t *base(reinterpret_cast<const uint8_t *>(stuff)); const struct exec *buf(reinterpret_cast<const struct exec *>(base)); if (OSSwapBigToHostInt32(buf->a_magic) == FAT_MAGIC) { struct host_basic_info hbi; { host_t host(mach_host_self()); mach_msg_type_number_t count(HOST_BASIC_INFO_COUNT); if (host_info(host, HOST_BASIC_INFO, reinterpret_cast<host_info_t>(&hbi), &count) != KERN_SUCCESS) return -1; mach_port_deallocate(mach_task_self(), host); } const struct fat_header *fh(reinterpret_cast<const struct fat_header *>(base)); uint32_t nfat_arch(OSSwapBigToHostInt32(fh->nfat_arch)); const struct fat_arch *fat_archs(reinterpret_cast<const struct fat_arch *>(fh + 1)); for (uint32_t i(0); i != nfat_arch; ++i) if (static_cast<cpu_type_t>(OSSwapBigToHostInt32(fat_archs[i].cputype)) == hbi.cpu_type) { buf = reinterpret_cast<const struct exec *>(base + OSSwapBigToHostInt32(fat_archs[i].offset)); goto thin; } return -1; } thin: const nlist_xx *symbols; const char *strings; size_t n; // XXX: this check looks really scary when it fails if (buf->a_magic == MH_MAGIC_XX) { const mach_header_xx *mh(reinterpret_cast<const mach_header_xx *>(base)); const struct load_command *load_commands(reinterpret_cast<const struct load_command *>(mh + 1)); const struct symtab_command *stp(NULL); const struct load_command *lcp; /* forlc (command, mh, LC_SYMTAB, struct symtab_command) { stp = command; goto found; } */ lcp = load_commands; for (uint32_t i(0); i != mh->ncmds; ++i) { if ( lcp->cmdsize % sizeof(long) != 0 || lcp->cmdsize <= 0 || reinterpret_cast<const uint8_t *>(lcp) + lcp->cmdsize > reinterpret_cast<const uint8_t *>(load_commands) + mh->sizeofcmds ) return -1; if (lcp->cmd == LC_SYMTAB) { if (lcp->cmdsize != sizeof(struct symtab_command)) return -1; stp = reinterpret_cast<const struct symtab_command *>(lcp); goto found; } lcp = reinterpret_cast<const struct load_command *>(reinterpret_cast<const uint8_t *>(lcp) + lcp->cmdsize); } return -1; found: n = stp->nsyms; symbols = NULL; strings = NULL; /* forlc (command, mh, LC_SEGMENT_XX, segment_command_xx) { stp = command; goto found; } */ lcp = load_commands; for (uint32_t i(0); i != mh->ncmds; ++i) { if ( lcp->cmdsize % sizeof(long) != 0 || lcp->cmdsize <= 0 || reinterpret_cast<const uint8_t *>(lcp) + lcp->cmdsize > reinterpret_cast<const uint8_t *>(load_commands) + mh->sizeofcmds ) return -1; if (lcp->cmd == LC_SEGMENT_XX) { if (lcp->cmdsize < sizeof(segment_command_xx)) return -1; const segment_command_xx *segment(reinterpret_cast<const segment_command_xx *>(lcp)); if (stp->symoff >= segment->fileoff && stp->symoff < segment->fileoff + segment->filesize) symbols = reinterpret_cast<const nlist_xx *>(stp->symoff - segment->fileoff + segment->vmaddr + slide); if (stp->stroff >= segment->fileoff && stp->stroff < segment->fileoff + segment->filesize) strings = reinterpret_cast<const char *>(stp->stroff - segment->fileoff + segment->vmaddr + slide); } lcp = reinterpret_cast<const struct load_command *>(reinterpret_cast<const uint8_t *>(lcp) + lcp->cmdsize); } if (symbols == NULL || strings == NULL) return -1; // XXX: detect a.out somehow? } else if (false) { /* XXX: is this right anymore?!? */ symbols = reinterpret_cast<const nlist_xx *>(base + N_SYMOFF(*buf)); strings = reinterpret_cast<const char *>(reinterpret_cast<const uint8_t *>(symbols) + buf->a_syms); n = buf->a_syms / sizeof(nlist_xx); } else return -1; size_t result(nreq); for (size_t m(0); m != n; ++m) { const nlist_xx *q(&symbols[m]); if (q->n_un.n_strx == 0 || (q->n_type & N_STAB) != 0) continue; const char *nambuf(strings + q->n_un.n_strx); //fprintf(stderr, " == %s\n", nambuf); for (size_t item(0); item != nreq; ++item) { struct MSSymbolData *p(list + item); if (p->name_ == NULL || strcmp(p->name_, nambuf) != 0) continue; p->name_ = NULL; p->value_ = q->n_value; if (p->value_ != 0) p->value_ += slide; p->type_ = q->n_type; p->desc_ = q->n_desc; p->sect_ = q->n_sect; if (--result == 0) return 0; break; } } return result; }
void BacktraceNames::FromAddr( const void *p ) { Address = (intptr_t) p; /* Find the image with the given pointer. */ int index = osx_find_image( p ); if( index == -1 ) return; File = _dyld_get_image_name( index ); /* Find the link-edit pointer. */ const char *link_edit = osx_find_link_edit( _dyld_get_image_header(index) ); if( link_edit == NULL ) return; link_edit += _dyld_get_image_vmaddr_slide( index ); unsigned long addr = (unsigned long)p - _dyld_get_image_vmaddr_slide(index); const struct mach_header *header = _dyld_get_image_header( index ); const struct load_command *cmd = (struct load_command *) &header[1]; unsigned long diff = 0xffffffff; const char *dli_sname = NULL; void *dli_saddr = NULL; for( unsigned long i = 0; i < header->ncmds; i++, cmd = next_load_command(cmd) ) { if( cmd->cmd != LC_SYMTAB ) continue; const symtab_command *scmd = (const symtab_command *) cmd; struct nlist *symtable = (struct nlist *)( link_edit + scmd->symoff ); for( unsigned long j = 0; j < scmd->nsyms; j++ ) { if( !symtable[j].n_value ) continue; /* Undefined */ if( symtable[j].n_type >= N_PEXT ) continue; /* Debug symbol */ if( addr >= symtable[j].n_value && diff >= (addr - symtable[j].n_value) ) { diff = addr - (unsigned long)symtable[j].n_value; dli_saddr = symtable[j].n_value + ((char *)p - addr); dli_sname = (const char *)( link_edit + scmd->stroff + symtable[j].n_un.n_strx ); } } } if( diff == 0xffffffff ) return; Symbol = dli_sname; Offset = (char*)(p)-(char*)dli_saddr; /* * __start -> _start * __ZN7RageLog5TraceEPKcz -> _ZN7RageLog5TraceEPKcz (so demangling will work) */ if( Symbol.Left(1) == "_" ) Symbol = Symbol.substr(1); /* After stripping off the leading _ * _GLOBAL__I__ZN5ModelC2Ev -> _ZN5ModelC2Ev * _GLOBAL__D__Z12ForceToAsciiR7CStdStrIcE -> _Z12ForceToAsciiR7CStdStrIcE */ if( Symbol.Left(9) == "_GLOBAL__" ) Symbol = Symbol.substr(11); }
int dladdr(void * p, Dl_info * info) { unsigned long i; unsigned long j; unsigned long count = _dyld_image_count(); struct mach_header *mh=0; struct load_command *lc=0; unsigned long addr = 0; int found = 0; if (!info) return 0; info->dli_fname = 0; info->dli_fbase = 0; info->dli_sname = 0; info->dli_saddr = 0; /* Some of this was swiped from code posted by Douglas Davidson <ddavidso AT apple DOT com> to darwin-development AT lists DOT apple DOT com and slightly modified */ for (i = 0; i < count; i++) { addr = (unsigned long)p - _dyld_get_image_vmaddr_slide(i); mh = _dyld_get_image_header(i); if (mh) { lc = (struct load_command *)((char *)mh + sizeof(struct mach_header)); for (j = 0; j < mh->ncmds; j++, lc = (struct load_command *)((char *)lc + lc->cmdsize)) { if (LC_SEGMENT == lc->cmd && addr >= ((struct segment_command *)lc)->vmaddr && addr < ((struct segment_command *)lc)->vmaddr + ((struct segment_command *)lc)->vmsize) { info->dli_fname = _dyld_get_image_name(i); info->dli_fbase = (void*)mh; found = 1; break; } } if (found) break; } } if (!found) return 0; /* Okay, we seem to have found a place for the address, so now, we have to search the symbol table for the nearest symbol with an address less than or equal to the passed in address */ lc = (struct load_command *)((char *)mh + sizeof(struct mach_header)); for (j = 0; j < mh->ncmds; j++, lc = (struct load_command *)((char *)lc + lc->cmdsize)) { if ( LC_SYMTAB == lc->cmd ) { struct nlist * symtable = (struct nlist *)(((struct symtab_command *)lc)->symoff + (void*)mh); unsigned long numsyms = ((struct symtab_command *)lc)->nsyms; struct nlist * nearest = NULL; unsigned long diff = 0xffffffff; unsigned long strtable = (unsigned long)(((struct symtab_command *)lc)->stroff + (void*)mh); for (i = 0; i < numsyms; i++) { /* Ignore the following kinds of Symbols */ if ((!symtable->n_value) /* Undefined */ || (symtable->n_type >= N_PEXT) /* Debug symbol */ || (!(symtable->n_type & N_EXT)) /* Local Symbol */ ) { symtable++; continue; } /* printf("info for symbol : %ld\n",i); printf("n_type: 0x%x\n",symtable->n_type); printf("n_sect: 0x%x\n",symtable->n_sect); printf("n_desc: 0x%x\n",symtable->n_desc); printf("n_value: 0x%x\n",symtable->n_value); printf("Name: %s\n",(char*)(strtable + symtable->n_un.n_strx )); */ if (( addr >= symtable->n_value) && (diff >= (symtable->n_value - addr))) { diff = symtable->n_value - addr; nearest = symtable; /* printf("Nearest is 0x%x\n",nearest); printf("Value: 0x%x\n",nearest->n_value); */ } symtable++; } if (nearest) { info->dli_saddr = nearest->n_value + (p - addr); info->dli_sname = (char*)(strtable + nearest->n_un.n_strx ); } } } return 1; }
primitiveExecutableModulesAndOffsets(void) { const struct mach_header *h; const struct mach_header_64 *h64; sqInt i; const char *name; char *nameObjData; sqInt nimages; sqInt resultObj; const struct section *s; const struct section_64 *s64; usqIntptr_t size; usqIntptr_t slide; usqIntptr_t start; sqInt valueObj; # if MAC_OS_X_VERSION_MIN_REQUIRED <= MAC_OS_X_VERSION_10_4 /* _dyld_present was deprecated in 10.5 */ if (!(_dyld_present())) { return primitiveFail(); } # endif /* MAC_OS_X_VERSION_MIN_REQUIRED <= MAC_OS_X_VERSION_10_4 */ nimages = _dyld_image_count(); resultObj = instantiateClassindexableSize(classArray(), nimages * 4); if (resultObj == 0) { return primitiveFail(); } pushRemappableOop(resultObj); for (i = 0; i < nimages; i += 1) { /* impossible start & size */ start = (size = -1); name = _dyld_get_image_name(i); slide = _dyld_get_image_vmaddr_slide(i); # if __x86_64__ h64 = (const struct mach_header_64 *)_dyld_get_image_header(i); if (!(h64 == null)) { s64 = getsectbynamefromheader_64(h64,SEG_TEXT,SECT_TEXT); if (!(s64 == null)) { start = s64->addr; size = s64->size; } } # else /* __x86_64__ */ h = _dyld_get_image_header(i); if (!(h == null)) { s = getsectbynamefromheader(h,SEG_TEXT,SECT_TEXT); if (!(s == null)) { start = s->addr; size = s->size; } } # endif /* __x86_64__ */ valueObj = instantiateClassindexableSize(classString(), strlen(name)); if (failed()) { popRemappableOop(); return primitiveFail(); } storePointerofObjectwithValue(i * 4, topRemappableOop(), valueObj); nameObjData = arrayValueOf(valueObj); memcpy(nameObjData, name, strlen(name)); valueObj = (BytesPerWord == 8 ? signed64BitIntegerFor(slide) : signed32BitIntegerFor(slide)); if (failed()) { popRemappableOop(); return primitiveFail(); } storePointerofObjectwithValue((i * 4) + 1, topRemappableOop(), valueObj); /* begin positiveMachineIntegerFor: */ valueObj = (BytesPerWord == 8 ? positive64BitIntegerFor(start) : positive32BitIntegerFor(start)); if (failed()) { popRemappableOop(); return primitiveFail(); } storePointerofObjectwithValue((i * 4) + 2, topRemappableOop(), valueObj); /* begin positiveMachineIntegerFor: */ valueObj = (BytesPerWord == 8 ? positive64BitIntegerFor(size) : positive32BitIntegerFor(size)); if (failed()) { popRemappableOop(); return primitiveFail(); } storePointerofObjectwithValue((i * 4) + 3, topRemappableOop(), valueObj); } resultObj = popRemappableOop(); return popthenPush(1, resultObj); }
void initialize_library(const char *uGensPluginPath) { gCmdLib = new HashTable<SC_LibCmd, Malloc>(&gMalloc, 64, true); gUnitDefLib = new HashTable<UnitDef, Malloc>(&gMalloc, 512, true); gBufGenLib = new HashTable<BufGen, Malloc>(&gMalloc, 512, true); gPlugInCmds = new HashTable<PlugInCmd, Malloc>(&gMalloc, 64, true); initMiscCommands(); #ifdef STATIC_PLUGINS IO_Load(&gInterfaceTable); Osc_Load(&gInterfaceTable); Delay_Load(&gInterfaceTable); BinaryOp_Load(&gInterfaceTable); Filter_Load(&gInterfaceTable); Gendyn_Load(&gInterfaceTable); LF_Load(&gInterfaceTable); Noise_Load(&gInterfaceTable); MulAdd_Load(&gInterfaceTable); Grain_Load(&gInterfaceTable); Pan_Load(&gInterfaceTable); Reverb_Load(&gInterfaceTable); Trigger_Load(&gInterfaceTable); UnaryOp_Load(&gInterfaceTable); DiskIO_Load(&gInterfaceTable); PhysicalModeling_Load(&gInterfaceTable); Test_Load(&gInterfaceTable); Demand_Load(&gInterfaceTable); DynNoise_Load(&gInterfaceTable); #if defined(SC_IPHONE) && !TARGET_IPHONE_SIMULATOR iPhone_Load(&gInterfaceTable); #endif return; #endif // If uGensPluginPath is supplied, it is exclusive. bool loadUGensExtDirs = true; if(uGensPluginPath){ loadUGensExtDirs = false; SC_StringParser sp(uGensPluginPath, SC_STRPARSE_PATHDELIMITER); while (!sp.AtEnd()) { PlugIn_LoadDir(const_cast<char *>(sp.NextToken()), true); } } if(loadUGensExtDirs) { #ifdef SC_PLUGIN_DIR // load globally installed plugins if (sc_DirectoryExists(SC_PLUGIN_DIR)) { PlugIn_LoadDir(SC_PLUGIN_DIR, true); } #endif // load default plugin directory char pluginDir[MAXPATHLEN]; sc_GetResourceDirectory(pluginDir, MAXPATHLEN); sc_AppendToPath(pluginDir, SC_PLUGIN_DIR_NAME); if (sc_DirectoryExists(pluginDir)) { PlugIn_LoadDir(pluginDir, true); } } // get extension directories char extensionDir[MAXPATHLEN]; if (!sc_IsStandAlone() && loadUGensExtDirs) { // load system extension plugins sc_GetSystemExtensionDirectory(extensionDir, MAXPATHLEN); PlugIn_LoadDir(extensionDir, false); // load user extension plugins sc_GetUserExtensionDirectory(extensionDir, MAXPATHLEN); PlugIn_LoadDir(extensionDir, false); // load user plugin directories SC_StringParser sp(getenv("SC_PLUGIN_PATH"), SC_STRPARSE_PATHDELIMITER); while (!sp.AtEnd()) { PlugIn_LoadDir(const_cast<char *>(sp.NextToken()), true); } } #ifdef SC_DARWIN /* on darwin plugins are lazily loaded (dlopen uses mmap internally), which can produce audible glitches when UGens have to be paged-in. to work around this we preload all the plugins by iterating through their memory space. */ unsigned long images = _dyld_image_count(); for(unsigned long i = 0; i < images; i++) { const mach_header *hdr = _dyld_get_image_header(i); unsigned long slide = _dyld_get_image_vmaddr_slide(i); const char *name = _dyld_get_image_name(i); uint32_t size; char *sect; if(!strcmp(name + (strlen(name) - 4), ".scx")) { read_section(hdr, slide, "__TEXT", "__text"); read_section(hdr, slide, "__TEXT", "__const"); read_section(hdr, slide, "__TEXT", "__cstring"); read_section(hdr, slide, "__TEXT", "__picsymbol_stub"); read_section(hdr, slide, "__TEXT", "__symbol_stub"); read_section(hdr, slide, "__TEXT", "__const"); read_section(hdr, slide, "__TEXT", "__literal4"); read_section(hdr, slide, "__TEXT", "__literal8"); read_section(hdr, slide, "__DATA", "__data"); read_section(hdr, slide, "__DATA", "__la_symbol_ptr"); read_section(hdr, slide, "__DATA", "__nl_symbol_ptr"); read_section(hdr, slide, "__DATA", "__dyld"); read_section(hdr, slide, "__DATA", "__const"); read_section(hdr, slide, "__DATA", "__mod_init_func"); read_section(hdr, slide, "__DATA", "__bss"); read_section(hdr, slide, "__DATA", "__common"); read_section(hdr, slide, "__IMPORT", "__jump_table"); read_section(hdr, slide, "__IMPORT", "__pointers"); } } #endif }
bool ksdl_dladdr(const uintptr_t address, Dl_info* const info) { info->dli_fname = NULL; info->dli_fbase = NULL; info->dli_sname = NULL; info->dli_saddr = NULL; const uint32_t idx = ksdl_imageIndexContainingAddress(address); if(idx == UINT_MAX) { return false; } const struct mach_header* header = _dyld_get_image_header(idx); const uintptr_t imageVMAddrSlide = (uintptr_t)_dyld_get_image_vmaddr_slide(idx); const uintptr_t addressWithSlide = address - imageVMAddrSlide; const uintptr_t segmentBase = ksdl_segmentBaseOfImageIndex(idx) + imageVMAddrSlide; if(segmentBase == 0) { return false; } info->dli_fname = _dyld_get_image_name(idx); info->dli_fbase = (void*)header; // Find symbol tables and get whichever symbol is closest to the address. const STRUCT_NLIST* bestMatch = NULL; uintptr_t bestDistance = ULONG_MAX; uintptr_t cmdPtr = ksdl_firstCmdAfterHeader(header); if(cmdPtr == 0) { return false; } for(uint32_t iCmd = 0; iCmd < header->ncmds; iCmd++) { const struct load_command* loadCmd = (struct load_command*)cmdPtr; if(loadCmd->cmd == LC_SYMTAB) { const struct symtab_command* symtabCmd = (struct symtab_command*)cmdPtr; const STRUCT_NLIST* symbolTable = (STRUCT_NLIST*)(segmentBase + symtabCmd->symoff); const uintptr_t stringTable = segmentBase + symtabCmd->stroff; for(uint32_t iSym = 0; iSym < symtabCmd->nsyms; iSym++) { // If n_value is 0, the symbol refers to an external object. if(symbolTable[iSym].n_value != 0) { uintptr_t symbolBase = symbolTable[iSym].n_value; uintptr_t currentDistance = addressWithSlide - symbolBase; if((addressWithSlide >= symbolBase) && (currentDistance <= bestDistance)) { bestMatch = symbolTable + iSym; bestDistance = currentDistance; } } } if(bestMatch != NULL) { info->dli_saddr = (void*)(bestMatch->n_value + imageVMAddrSlide); info->dli_sname = (char*)((intptr_t)stringTable + (intptr_t)bestMatch->n_un.n_strx); if(*info->dli_sname == '_') { info->dli_sname++; } // This happens if all symbols have been stripped. if(info->dli_saddr == info->dli_fbase && bestMatch->n_type == 3) { info->dli_sname = NULL; } break; } } cmdPtr += loadCmd->cmdsize; } return true; }
int darwin_dladdr(void *p, Dl_info *info) { unsigned long i; unsigned long j; uint32_t count = _dyld_image_count(); struct mach_header *mh = 0; struct load_command *lc = 0; unsigned long addr = 0; unsigned long table_off = (unsigned long)0; int found = 0; if (!info) return 0; info->dli_fname = 0; info->dli_fbase = 0; info->dli_sname = 0; info->dli_saddr = 0; /* Some of this was swiped from code posted by Douglas Davidson * <ddavidso AT apple DOT com> to darwin-development AT lists DOT * apple DOT com and slightly modified */ for (i = 0; i < count; i++) { addr = (unsigned long)p - _dyld_get_image_vmaddr_slide(i); mh = (struct mach_header *)_dyld_get_image_header(i); if (mh) { lc = (struct load_command *)((char *)mh + sizeof(struct mach_header)); for (j = 0; j < mh->ncmds; j++, lc = (struct load_command *)((char *)lc + lc->cmdsize)) { if (LC_SEGMENT == lc->cmd && addr >= ((struct segment_command *)lc)->vmaddr && addr < ((struct segment_command *)lc)->vmaddr + ((struct segment_command *)lc)->vmsize) { info->dli_fname = _dyld_get_image_name(i); info->dli_fbase = (void *)mh; found = 1; break; } } if (found) { break; } } } if (!found) { return 0; } lc = (struct load_command *)((char *)mh + sizeof(struct mach_header)); for (j = 0; j < mh->ncmds; j++, lc = (struct load_command *)((char *)lc + lc->cmdsize)) { if (LC_SEGMENT == lc->cmd) { if (!strcmp(((struct segment_command *)lc)->segname, "__LINKEDIT")) break; } } table_off = ((unsigned long)((struct segment_command *)lc)->vmaddr) - ((unsigned long)((struct segment_command *)lc)->fileoff) + _dyld_get_image_vmaddr_slide(i); lc = (struct load_command *)((char *)mh + sizeof(struct mach_header)); for (j = 0; j < mh->ncmds; j++, lc = (struct load_command *)((char *)lc + lc->cmdsize)) { if (LC_SYMTAB == lc->cmd) { struct nlist *symtable = (struct nlist *)(((struct symtab_command *)lc)->symoff + table_off); unsigned long numsyms = ((struct symtab_command *)lc)->nsyms; struct nlist *nearest = NULL; unsigned long diff = 0xffffffff; unsigned long strtable = (unsigned long)(((struct symtab_command *)lc)->stroff + table_off); for (i = 0; i < numsyms; i++) { /* fprintf(dbgout,"%s : 0x%08x, 0x%x\n",(char *)(strtable + symtable->n_un.n_strx) ,symtable->n_value, symtable->n_type); */ /* Ignore the following kinds of Symbols */ if ((!symtable->n_value) /* Undefined */ || (symtable->n_type & N_STAB) /* Debug symbol */ || ((symtable->n_type & N_TYPE) != N_SECT) /* Absolute, indirect, ... */ ) { symtable++; continue; } if ((addr >= symtable->n_value) && (diff >= addr - (symtable->n_value ))) { diff = addr- (unsigned long)symtable->n_value; nearest = symtable; } symtable++; } if (nearest) { info->dli_saddr = nearest->n_value + ((void *)p - addr); info->dli_sname = (char *)(strtable + nearest->n_un.n_strx); } } } return 1; }
MODULE_SCOPE void * TkMacOSXGetNamedDebugSymbol( const char* module, const char* symbol) { void* addr = TkMacOSXGetNamedSymbol(module, symbol); #ifndef __LP64__ if (!addr) { const struct mach_header *mh = NULL; uint32_t i, n = _dyld_image_count(); size_t module_len = 0; if (module && *module) { module_len = strlen(module); } for (i = 0; i < n; i++) { if (module && *module) { /* Find image with given module name */ char *name; const char *path = _dyld_get_image_name(i); if (!path) { continue; } name = strrchr(path, '/') + 1; if (strncmp(name, module, module_len) != 0) { continue; } } mh = _dyld_get_image_header(i); if (mh) { struct load_command *lc; struct symtab_command *st = NULL; struct segment_command *sg = NULL; uint32_t j, m, nsect = 0, txtsectx = 0; lc = (struct load_command*)((const char*) mh + sizeof(struct mach_header)); m = mh->ncmds; for (j = 0; j < m; j++) { /* Find symbol table and index of __text section */ if (lc->cmd == LC_SEGMENT) { /* Find last segment before symbol table */ sg = (struct segment_command*) lc; if (!txtsectx) { /* Count total sections until (__TEXT, __text) */ uint32_t k, ns = sg->nsects; if (strcmp(sg->segname, SEG_TEXT) == 0) { struct section *s = (struct section *)( (char *)sg + sizeof(struct segment_command)); for(k = 0; k < ns; k++) { if (strcmp(s->sectname, SECT_TEXT) == 0) { txtsectx = nsect+k+1; break; } s++; } } nsect += ns; } } else if (!st && lc->cmd == LC_SYMTAB) { st = (struct symtab_command*) lc; break; } lc = (struct load_command *)((char *) lc + lc->cmdsize); } if (st && sg && txtsectx) { intptr_t base, slide = _dyld_get_image_vmaddr_slide(i); char *strings; struct nlist *sym; uint32_t strsize = st->strsize; int32_t strx; /* Offset file positions by difference to actual position in memory of last segment before symbol table: */ base = (intptr_t) sg->vmaddr + slide - sg->fileoff; strings = (char*)(base + st->stroff); sym = (struct nlist*)(base + st->symoff); m = st->nsyms; for (j = 0; j < m; j++) { /* Find symbol with given name in __text section */ strx = sym->n_un.n_strx; if ((sym->n_type & N_TYPE) == N_SECT && sym->n_sect == txtsectx && strx > 0 && (uint32_t) strx < strsize && strcmp(strings + strx, symbol) == 0) { addr = (char*) sym->n_value + slide; break; } sym++; } } } if (module && *module) { /* If given a module name, only search corresponding image */ break; } } } #endif /* __LP64__ */ return addr; }
primitiveExecutableModulesAndOffsets(void) { const struct mach_header *h; sqInt i; const char *name; char *nameObjData; sqInt nimages; sqInt present; sqInt resultObj; const struct section *s; unsigned long size; sqInt slide; unsigned long start; sqInt valueObj; present = _dyld_present(); if (!(present)) { return interpreterProxy->primitiveFail(); } nimages = _dyld_image_count(); resultObj = interpreterProxy->instantiateClassindexableSize(interpreterProxy->classArray(), nimages * 4); if (resultObj == 0) { return interpreterProxy->primitiveFail(); } interpreterProxy->pushRemappableOop(resultObj); for (i = 0; i <= (nimages - 1); i += 1) { /* impossible start & size */ start = size = -1; name = _dyld_get_image_name(i); slide = _dyld_get_image_vmaddr_slide(i); h = _dyld_get_image_header(i); if (h != null) { s = getsectbynamefromheader(h,SEG_TEXT,SECT_TEXT); if (s != null) { start = s->addr; size = s->size; } } valueObj = interpreterProxy->instantiateClassindexableSize(interpreterProxy->classString(), strlen(name)); if (interpreterProxy->failed()) { interpreterProxy->pop(1); return interpreterProxy->primitiveFail(); } interpreterProxy->storePointerofObjectwithValue(i * 4, interpreterProxy->topRemappableOop(), valueObj); nameObjData = interpreterProxy->arrayValueOf(valueObj); memcpy(nameObjData, name, strlen(name)); valueObj = interpreterProxy->signed32BitIntegerFor(slide); if (interpreterProxy->failed()) { interpreterProxy->pop(1); return interpreterProxy->primitiveFail(); } interpreterProxy->storePointerofObjectwithValue((i * 4) + 1, interpreterProxy->topRemappableOop(), valueObj); valueObj = interpreterProxy->positive32BitIntegerFor(start); if (interpreterProxy->failed()) { interpreterProxy->pop(1); return interpreterProxy->primitiveFail(); } interpreterProxy->storePointerofObjectwithValue((i * 4) + 2, interpreterProxy->topRemappableOop(), valueObj); valueObj = interpreterProxy->positive32BitIntegerFor(size); if (interpreterProxy->failed()) { interpreterProxy->pop(1); return interpreterProxy->primitiveFail(); } interpreterProxy->storePointerofObjectwithValue((i * 4) + 3, interpreterProxy->topRemappableOop(), valueObj); } resultObj = interpreterProxy->popRemappableOop(); return interpreterProxy->popthenPush(1, resultObj); }