[llvm-dev] Debugging an Objective-C metadata-emit problem, Bug #30413

Mehdi Amini via llvm-dev llvm-dev at lists.llvm.org
Tue Jan 17 08:49:19 PST 2017


CC: cfe-dev (and tweak the title) ; this is really a frontend question.

— 
Mehdi

> On Jan 17, 2017, at 7:31 AM, Lobron, David via llvm-dev <llvm-dev at lists.llvm.org> wrote:
> 
> Hello llvm-dev,
> 
> I opened bug report 30413 a while ago, and I'd like to request help from someone with better knowledge of clang.  The bug occurs on Linux, where clang does not emit type metadata when compiling Objective-C programs, as it does on the Mac, and as gcc does on Linux.  My program uses that metadata to do type introspection (see below for an example).
> 
> From code inspection, it appears that the type metadata is written by code in clang's ASTContext class.  I wrote a test program, copied below, which reproduces this bug.  I ran clang under gdb, and set a breakpoint on all the methods in the clang::ASTContext:: namespace, but I found that none of these were called (at least, none of the 571 breakpoints was triggered).  I confirmed that other gdb breakpoints (e.g., on ::main) did get triggered, so I know that my breakpoints in general were working. 
> 
> I was left with two questions:
> 
> - Are the clang::ASTContext:: methods not called when compiling an ObjC program?
> 
> - Is there some other part of the code where the metadata is emitted, if not from clang::ASTContext::?  I looked for a quite a while, but I could not find a plausible candidate.
> 
> Any help would be appreciated!  Feel free to reply to me directly, or to the list, or to post suggestions in the bug report here:
> 
> https://llvm.org/bugs/show_bug.cgi?id=30413
> 
> Thanks!
> 
> --David
> 
> My test program code is below.  On a Mac, compiled with clang, the runtime can correctly introspect the type of an NSString* instance variable.  The output is:
> 
> 2017-01-17 10:26:21.333 TestClassMetadata[13856:3607976] Ivar type _intIvar does not appear to be an object-valued class: type is i
> 2017-01-17 10:26:21.334 TestClassMetadata[13856:3607976] Ivar type _doubleVar does not appear to be an object-valued class: type is d
> 2017-01-17 10:26:21.334 TestClassMetadata[13856:3607976] Introspected class NSString for ivar name _stringIvar
> 
> On Linux, compiled with clang, the NSString introspection does not work, because the metadata is not present.  The output there is:
> 
> 2017-01-17 15:27:15.641 TestClassMetadata[32308:32308] Ivar type _intIvar does not appear to be an object-valued class: type is i
> 2017-01-17 15:27:15.661 TestClassMetadata[32308:32308] Ivar type _doubleVar does not appear to be an object-valued class: type is d
> 2017-01-17 15:27:15.661 TestClassMetadata[32308:32308] Ivar type _stringIvar does not appear to be an object-valued class: type is @
> 
> (Note the difference in the last lines).
> 
> Program code:
> 
> #import <Foundation/Foundation.h>
> 
> #ifdef __APPLE__
> #import <objc/objc-runtime.h>
> #else
> #import <objc/runtime.h>
> #endif
> 
> @interface TestClass : NSObject {
>    @public
>    int         _intIvar;
>    double      _doubleVar;
>    NSString    *_stringIvar;
> }
> - (id)init;
> - (void)sayHello:(NSString *)txt;
> @end
> 
> @implementation TestClass
> 
> - (void)sayHello:(NSString *)txt 
> {
>  [_stringIvar release];
>  _stringIvar = [txt retain];
>  NSLog(@"%@", _stringIvar);
> }
> 
> - (void)dealloc
> {
>  [_stringIvar release];
>  [super dealloc];
> }
> 
> - (id)init {
>    if ((self = [super init]) != nil) {
>        unsigned i;
>        Class c = [self class];
>        NSAssert(c != 0, @"Could not get class object");
> 	unsigned ivarCount;
> 	Ivar *ivarList = class_copyIvarList(c, &ivarCount);
> 	for (i = 0; i < ivarCount; i++) {
> 	    Ivar ivar = ivarList[i];
> 	    const char *ivarCname = ivar_getName(ivar);
> 	    if (ivarCname != 0) {
> 		NSString *ivarName = [NSString stringWithUTF8String:ivarCname];
> 		const char *ivarType = ivar_getTypeEncoding(ivar);
> 		if (ivarType[0] == '@' && ivarType[1] == '"') {
> 		    NSString *className = [[[NSString alloc] initWithBytes: &ivarType[2]
> 							     length: strlen(&ivarType[2])-1
> 							     encoding: NSUTF8StringEncoding] autorelease];
> 		    Class c = NSClassFromString(className);
> 		    if (c == nil) {
> 			NSLog(@"WARNING: unknown class name \"%@\" in declaration of %@", className, [self class]);
> 		    } else {
> 			NSLog(@"Introspected class %@ for ivar name %@",
> 			      className, ivarName);
> 		    }
> 		} else {
> 		    NSLog(@"Ivar type %s does not appear to be an object-valued class: type is %s", ivarCname, ivarType);
> 		}
> 	    }
> 	}
> 	if (ivarList)
> 	    free(ivarList);
>    }
> 
>    return self;
> }
> 
> @end
> 
> int main() {
>    NSAutoreleasePool *pool = [NSAutoreleasePool new];
>    TestClass *c = [[[TestClass alloc] init] autorelease];
>    [pool release];
> 
>    return 0;
> }
> _______________________________________________
> LLVM Developers mailing list
> llvm-dev at lists.llvm.org
> http://lists.llvm.org/cgi-bin/mailman/listinfo/llvm-dev



More information about the llvm-dev mailing list