make class lookup more reliable

This commit is contained in:
Richard Frith-Macdonald 2019-02-14 12:37:44 +00:00
parent d6ef10f224
commit 911c5cdd66
5 changed files with 55 additions and 74 deletions

View file

@ -1,3 +1,13 @@
2019-02-14 Richard Frith-Macdonald <rfm@gnu.org>
* Source/GSPrivate.h:
* Source/NSBundle.m:
* Source/NSPathUtilities.m:
* Source/objc-load.m:
GSPrivateSymbolPath() simplified by removing the unused argument
and consolidated code so that, if the class lookup via dladdr()
fails, we fall back to use __objc_dynamic_get_symbol_path().
2019-02-14 Richard Frith-Macdonald <rfm@gnu.org> 2019-02-14 Richard Frith-Macdonald <rfm@gnu.org>
* Source/Additions/GSMime.m: Fix encoded word encoding specifier * Source/Additions/GSMime.m: Fix encoded word encoding specifier

View file

@ -501,16 +501,12 @@ GSPrivateStrExternalize(GSStr s) GS_ATTRIB_PRIVATE;
* argv[0] (which might be something as horrible as './obj/test') * argv[0] (which might be something as horrible as './obj/test')
* for classes in the main executable. * for classes in the main executable.
* *
* If theCategory argument is not NULL, GSPrivateSymbolPath() will return
* the filesystem path to the module from which the category theCategory
* of the class theClass was loaded.
*
* Currently, the function will return nil if any of the following * Currently, the function will return nil if any of the following
* conditions is satisfied: * conditions is satisfied:
* - the required functionality is not available on the platform we are * - the required functionality is not available on the platform we are
* running on; * running on;
* - memory allocation fails; * - memory allocation fails;
* - the symbol for that class/category could not be found. * - the symbol for that class could not be found.
* *
* In general, if the function returns nil, it means something serious * In general, if the function returns nil, it means something serious
* went wrong in the system preventing it from getting the symbol path. * went wrong in the system preventing it from getting the symbol path.
@ -521,7 +517,7 @@ GSPrivateStrExternalize(GSStr s) GS_ATTRIB_PRIVATE;
* runtime ... as far as I know. * runtime ... as far as I know.
*/ */
NSString * NSString *
GSPrivateSymbolPath (Class theClass, Category *theCategory) GS_ATTRIB_PRIVATE; GSPrivateSymbolPath(Class theClass) GS_ATTRIB_PRIVATE;
/* Combining class for composite unichars /* Combining class for composite unichars
*/ */

View file

@ -724,7 +724,7 @@ _find_main_bundle_for_tool(NSString *toolName)
* really universal way of getting the framework path ... we can * really universal way of getting the framework path ... we can
* locate the framework no matter where it is on disk! * locate the framework no matter where it is on disk!
*/ */
bundlePath = GSPrivateSymbolPath (frameworkClass, NULL); bundlePath = GSPrivateSymbolPath(frameworkClass);
if ([bundlePath isEqualToString: GSPrivateExecutablePath()]) if ([bundlePath isEqualToString: GSPrivateExecutablePath()])
{ {
@ -1078,7 +1078,7 @@ _bundle_load_callback(Class theClass, struct objc_category *theCategory)
_emptyTable = [NSDictionary new]; _emptyTable = [NSDictionary new];
/* Create basic mapping dictionaries for bootstrapping and /* Create basic mapping dictionaries for bootstrapping and
* for use if the full ductionaries can't be loaded from the * for use if the full dictionaries can't be loaded from the
* gnustep-base library resource bundle. * gnustep-base library resource bundle.
*/ */
langAliases = [[NSDictionary alloc] initWithObjectsAndKeys: langAliases = [[NSDictionary alloc] initWithObjectsAndKeys:
@ -1513,7 +1513,7 @@ _bundle_load_callback(Class theClass, struct objc_category *theCategory)
[load_lock lock]; [load_lock lock];
/* Try lookup ... if not found, make sure that all loaded bundles have /* Try lookup ... if not found, make sure that all loaded bundles have
* class->bundle mapp entries set up and check again. * class->bundle map entries set up and check again.
*/ */
bundle = (NSBundle *)NSMapGet(_byClass, aClass); bundle = (NSBundle *)NSMapGet(_byClass, aClass);
if ((id)bundle == (id)[NSNull null]) if ((id)bundle == (id)[NSNull null])
@ -1561,7 +1561,7 @@ _bundle_load_callback(Class theClass, struct objc_category *theCategory)
* convert it to the format for a library name as used for * convert it to the format for a library name as used for
* obtaining a library resource bundle. * obtaining a library resource bundle.
*/ */
lib = GSPrivateSymbolPath (aClass, NULL); lib = GSPrivateSymbolPath(aClass);
if ([lib isEqual: GSPrivateExecutablePath()] == YES) if ([lib isEqual: GSPrivateExecutablePath()] == YES)
{ {
lib = nil; // In program, not library. lib = nil; // In program, not library.
@ -2707,7 +2707,7 @@ IF_NO_GC(
} }
if (self->_bundleType == NSBUNDLE_LIBRARY) if (self->_bundleType == NSBUNDLE_LIBRARY)
{ {
return GSPrivateSymbolPath ([self principalClass], NULL); return GSPrivateSymbolPath([self principalClass]);
} }
object = [[self infoDictionary] objectForKey: @"NSExecutable"]; object = [[self infoDictionary] objectForKey: @"NSExecutable"];
if (object == nil || [object length] == 0) if (object == nil || [object length] == 0)

View file

@ -961,7 +961,7 @@ GNUstepConfig(NSDictionary *newConfig)
{ {
Class c = [NSProcessInfo class]; Class c = [NSProcessInfo class];
path = GSPrivateSymbolPath (c, 0); path = GSPrivateSymbolPath(c);
// Remove library name from path // Remove library name from path
path = [path stringByDeletingLastPathComponent]; path = [path stringByDeletingLastPathComponent];
if ([file hasPrefix: @"./"] == YES) if ([file hasPrefix: @"./"] == YES)

View file

@ -246,12 +246,11 @@ GSPrivateUnloadModule(FILE *errorStream,
// dladdr() wrapping this function, so we no longer need a Windows-only code // dladdr() wrapping this function, so we no longer need a Windows-only code
// path // path
NSString * NSString *
GSPrivateSymbolPath(Class theClass, Category *theCategory) GSPrivateSymbolPath(Class theClass)
{ {
unichar buf[MAX_PATH]; unichar buf[MAX_PATH];
NSString *s = nil; NSString *s = nil;
MEMORY_BASIC_INFORMATION memInfo; MEMORY_BASIC_INFORMATION memInfo;
NSCAssert(!theCategory, @"GSPrivateSymbolPath doesn't support categories");
VirtualQueryEx(GetCurrentProcess(), theClass, &memInfo, sizeof(memInfo)); VirtualQueryEx(GetCurrentProcess(), theClass, &memInfo, sizeof(memInfo));
if (GetModuleFileNameW(memInfo.AllocationBase, buf, sizeof(buf))) if (GetModuleFileNameW(memInfo.AllocationBase, buf, sizeof(buf)))
@ -263,81 +262,57 @@ GSPrivateSymbolPath(Class theClass, Category *theCategory)
} }
return s; return s;
} }
#elif LINKER_GETSYMBOL #else
NSString *GSPrivateSymbolPath(Class theClass, Category *theCategory) NSString *GSPrivateSymbolPath(Class theClass)
{ {
void *addr = (NULL == theCategory) ? (void*)theClass : (void*)theCategory; #if LINKER_GETSYMBOL
Dl_info info; Dl_info info;
/* This is correct: dladdr() does the opposite thing to all other UNIX /* This is correct: dladdr() does the opposite thing to all other UNIX
* functions. * functions.
* On success, return the results, otherwise fall back to use the
* __objc_dynamic_get_symbol_path() function.
*/ */
if (0 == dladdr(addr, &info)) if (0 != dladdr((void*)theClass, &info))
{ {
return nil; return [NSString stringWithUTF8String: info.dli_fname];
} }
return [NSString stringWithUTF8String: info.dli_fname]; #endif
}
#else
NSString *
GSPrivateSymbolPath(Class theClass, Category *theCategory)
{
const char *ret;
char buf[125], *p = buf;
const char *className = class_getName(theClass);
int len = strlen(className);
if (theCategory == NULL) if (theClass != nil)
{ {
if (len + sizeof(char)*19 > sizeof(buf)) const char *ret;
{ char buf[125];
p = malloc(len + sizeof(char)*19); char *p = buf;
const char *className = class_getName(theClass);
int len = strlen(className);
if (p == NULL) if (len + sizeof(char)*19 > sizeof(buf))
{ {
fprintf(stderr, "Unable to allocate memory !!"); p = malloc(len + sizeof(char)*19);
return nil;
} if (p == NULL)
} {
fprintf(stderr, "Unable to allocate memory !!");
return nil;
}
}
memcpy(p, "__objc_class_name_", sizeof(char)*18); memcpy(p, "__objc_class_name_", sizeof(char)*18);
memcpy(&p[18*sizeof(char)], className, strlen(className) + 1); memcpy(&p[18*sizeof(char)], className, strlen(className) + 1);
ret = __objc_dynamic_get_symbol_path(0, p);
if (p != buf)
{
free(p);
}
if (ret)
{
return [NSString stringWithUTF8String: ret];
}
} }
else
{
len += strlen(theCategory->category_name);
if (len + sizeof(char)*23 > sizeof(buf))
{
p = malloc(len + sizeof(char)*23);
if (p == NULL)
{
fprintf(stderr, "Unable to allocate memory !!");
return nil;
}
}
memcpy(p, "__objc_category_name_", sizeof(char)*21);
memcpy(&p[21*sizeof(char)], theCategory->class_name,
strlen(theCategory->class_name) + 1);
memcpy(&p[strlen(p)], "_", 2*sizeof(char));
memcpy(&p[strlen(p)], theCategory->category_name,
strlen(theCategory->category_name) + 1);
}
ret = __objc_dynamic_get_symbol_path(0, p);
if (p != buf)
{
free(p);
}
if (ret)
{
return [NSString stringWithUTF8String: ret];
}
return nil; return nil;
} }
#endif #endif