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>
* 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')
* 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
* conditions is satisfied:
* - the required functionality is not available on the platform we are
* running on;
* - 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
* 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.
*/
NSString *
GSPrivateSymbolPath (Class theClass, Category *theCategory) GS_ATTRIB_PRIVATE;
GSPrivateSymbolPath(Class theClass) GS_ATTRIB_PRIVATE;
/* 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
* locate the framework no matter where it is on disk!
*/
bundlePath = GSPrivateSymbolPath (frameworkClass, NULL);
bundlePath = GSPrivateSymbolPath(frameworkClass);
if ([bundlePath isEqualToString: GSPrivateExecutablePath()])
{
@ -1078,7 +1078,7 @@ _bundle_load_callback(Class theClass, struct objc_category *theCategory)
_emptyTable = [NSDictionary new];
/* 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.
*/
langAliases = [[NSDictionary alloc] initWithObjectsAndKeys:
@ -1513,7 +1513,7 @@ _bundle_load_callback(Class theClass, struct objc_category *theCategory)
[load_lock lock];
/* 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);
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
* obtaining a library resource bundle.
*/
lib = GSPrivateSymbolPath (aClass, NULL);
lib = GSPrivateSymbolPath(aClass);
if ([lib isEqual: GSPrivateExecutablePath()] == YES)
{
lib = nil; // In program, not library.
@ -2707,7 +2707,7 @@ IF_NO_GC(
}
if (self->_bundleType == NSBUNDLE_LIBRARY)
{
return GSPrivateSymbolPath ([self principalClass], NULL);
return GSPrivateSymbolPath([self principalClass]);
}
object = [[self infoDictionary] objectForKey: @"NSExecutable"];
if (object == nil || [object length] == 0)

View file

@ -961,7 +961,7 @@ GNUstepConfig(NSDictionary *newConfig)
{
Class c = [NSProcessInfo class];
path = GSPrivateSymbolPath (c, 0);
path = GSPrivateSymbolPath(c);
// Remove library name from path
path = [path stringByDeletingLastPathComponent];
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
// path
NSString *
GSPrivateSymbolPath(Class theClass, Category *theCategory)
GSPrivateSymbolPath(Class theClass)
{
unichar buf[MAX_PATH];
NSString *s = nil;
MEMORY_BASIC_INFORMATION memInfo;
NSCAssert(!theCategory, @"GSPrivateSymbolPath doesn't support categories");
VirtualQueryEx(GetCurrentProcess(), theClass, &memInfo, sizeof(memInfo));
if (GetModuleFileNameW(memInfo.AllocationBase, buf, sizeof(buf)))
@ -263,32 +262,31 @@ GSPrivateSymbolPath(Class theClass, Category *theCategory)
}
return s;
}
#elif LINKER_GETSYMBOL
NSString *GSPrivateSymbolPath(Class theClass, Category *theCategory)
#else
NSString *GSPrivateSymbolPath(Class theClass)
{
void *addr = (NULL == theCategory) ? (void*)theClass : (void*)theCategory;
#if LINKER_GETSYMBOL
Dl_info info;
/* This is correct: dladdr() does the opposite thing to all other UNIX
* 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];
}
#else
NSString *
GSPrivateSymbolPath(Class theClass, Category *theCategory)
#endif
if (theClass != nil)
{
const char *ret;
char buf[125], *p = buf;
char buf[125];
char *p = buf;
const char *className = class_getName(theClass);
int len = strlen(className);
if (theCategory == NULL)
{
if (len + sizeof(char)*19 > sizeof(buf))
{
p = malloc(len + sizeof(char)*19);
@ -302,29 +300,6 @@ GSPrivateSymbolPath(Class theClass, Category *theCategory)
memcpy(p, "__objc_class_name_", sizeof(char)*18);
memcpy(&p[18*sizeof(char)], className, strlen(className) + 1);
}
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);
@ -337,7 +312,7 @@ GSPrivateSymbolPath(Class theClass, Category *theCategory)
{
return [NSString stringWithUTF8String: ret];
}
}
return nil;
}
#endif