Mercurial > hg > xemacs-beta
changeset 1851:7fdde2d3ae5f
[xemacs-hg @ 2004-01-03 23:06:49 by james]
Malcolm Purvis' patch to add MacOS X dynamic lib support.
author | james |
---|---|
date | Sat, 03 Jan 2004 23:06:51 +0000 |
parents | 38f35d20ac8c |
children | c8dcd54b0cc0 |
files | src/ChangeLog src/sysdll.c |
diffstat | 2 files changed, 158 insertions(+), 5 deletions(-) [+] |
line wrap: on
line diff
--- a/src/ChangeLog Sat Jan 03 22:50:31 2004 +0000 +++ b/src/ChangeLog Sat Jan 03 23:06:51 2004 +0000 @@ -1,3 +1,11 @@ +2003-12-29 Malcolm Purvis <malcolmpurvis@optushome.com.au> + + * sysdll.c (dll_function): Added support for finding symbols in + Darwin shared libraries as well in Darwin bundles. + * sysdll.c (image_for_address): New. + * sysdll.c (my_find_image): New. + * sysdll.c (search_linked_libs): New. + 2004-01-03 James C. McPherson <james.mcpherson@optusnet.com.au> * doc.c (Fdocumentation_property): GCPROd variables cannot be
--- a/src/sysdll.c Sat Jan 03 22:50:31 2004 +0000 +++ b/src/sysdll.c Sat Jan 03 23:06:51 2004 +0000 @@ -277,15 +277,160 @@ return NSUnLinkModule((NSModule)h, NSUNLINKMODULE_OPTION_NONE); } +/* Given an address, return the mach_header for the image containing it + * or zero if the given address is not contained in any loaded images. + * + * Note: image_for_address(), my_find_image() and search_linked_libs() are + * based on code from the dlcompat library + * (http://www.opendarwin.org/projects/dlcompat). + */ + +static struct mach_header* +image_for_address(void *address) +{ + unsigned long i; + unsigned long count = _dyld_image_count(); + struct mach_header *mh = 0; + + for (i = 0; i < count; i++) + { + unsigned long addr = (unsigned long)address - + _dyld_get_image_vmaddr_slide(i); + mh = _dyld_get_image_header(i); + + if (mh) + { + struct load_command *lc = + (struct load_command *)((char *)mh + sizeof(struct mach_header)); + unsigned long j; + + 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) + { + goto image_found; + } + } + } + + mh = 0; + } + + image_found: + return mh; +} + +static const struct mach_header* +my_find_image(const char *name) +{ + const struct mach_header *mh = (struct mach_header *) + NSAddImage(name, NSADDIMAGE_OPTION_RETURN_ONLY_IF_LOADED | + NSADDIMAGE_OPTION_RETURN_ON_ERROR); + + if (!mh) + { + int count = _dyld_image_count(); + int j; + + for (j = 0; j < count; j++) + { + const char *id = _dyld_get_image_name(j); + + if (!strcmp(id, name)) + { + mh = _dyld_get_image_header(j); + break; + } + } + } + + return mh; +} + +/* + * dyld adds libraries by first adding the directly dependant libraries in + * link order, and then adding the dependencies for those libraries, so we + * should do the same... but we don't bother adding the extra dependencies, if + * the symbols are neither in the loaded image nor any of it's direct + * dependencies, then it probably isn't there. + */ +static NSSymbol +search_linked_libs(const struct mach_header * mh, const char *symbol) +{ + int n; + NSSymbol nssym = 0; + + struct load_command *lc = + (struct load_command *)((char *)mh + sizeof(struct mach_header)); + + for (n = 0; n < mh->ncmds; + n++, lc = (struct load_command *)((char *)lc + lc->cmdsize)) + { + if ((LC_LOAD_DYLIB == lc->cmd) || (LC_LOAD_WEAK_DYLIB == lc->cmd)) + { + struct mach_header *wh; + + if ((wh = (struct mach_header *) + my_find_image((char *)(((struct dylib_command *)lc)->dylib.name.offset + + (char *)lc)))) + { + if (NSIsSymbolNameDefinedInImage(wh, symbol)) + { + nssym = + NSLookupSymbolInImage(wh, + symbol, + NSLOOKUPSYMBOLINIMAGE_OPTION_BIND | + NSLOOKUPSYMBOLINIMAGE_OPTION_RETURN_ON_ERROR); + break; + } + } + } + } + + return nssym; +} + dll_func dll_function (dll_handle h, const CIbyte *n) { - NSSymbol sym; + NSSymbol sym = 0; MAYBE_PREPEND_UNDERSCORE (n); - sym = NSLookupSymbolInModule((NSModule)h, n); - if (sym == 0) return 0; - return (dll_func)NSAddressOfSymbol(sym); -} + + /* NULL means the program image and shared libraries, not bundles. */ + + if (h == NULL) + { + /* NOTE: This assumes that this function is included in the main program + and not in a shared library. */ + const struct mach_header* my_mh = image_for_address(&dll_function); + + if (NSIsSymbolNameDefinedInImage(my_mh, n)) + { + sym = + NSLookupSymbolInImage(my_mh, + n, + NSLOOKUPSYMBOLINIMAGE_OPTION_BIND | + NSLOOKUPSYMBOLINIMAGE_OPTION_RETURN_ON_ERROR); + } + + if (!sym) + { + sym = search_linked_libs(my_mh, n); + } + } + else + { + sym = NSLookupSymbolInModule((NSModule)h, n); + } + + if (sym == 0) return 0; + return (dll_func)NSAddressOfSymbol(sym); + } dll_var dll_variable (dll_handle h, const CIbyte *n)