Lobron, David via llvm-dev
2017-Jan-17 15:31 UTC
[llvm-dev] Debugging a metadata-emit problem, Bug #30413
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; }
Mehdi Amini via llvm-dev
2017-Jan-17 16:49 UTC
[llvm-dev] Debugging an Objective-C metadata-emit problem, Bug #30413
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