[LLVMdev] Trouble Resolving Objective-C Symbols in lli

Chris Lattner sabre at nondot.org
Thu Jul 19 14:56:34 PDT 2007


On Thu, 19 Jul 2007, Andy Kitchen wrote:
> Hi there, I'm trying to run trivial Objective-C code that uses the 
> Foundation framework under MacOS X in lli. It seems that the code will 
> compile and run using llc, however fails to work in lli.

Nice!  this is a great project, unfortunately, there are some issues here 
:)

I'm CC'ing Marcel, as he has some experience with dynamic generation of 
code with the objc runtime library.

> SimpleFoundation.m:
> ----
>
> #import <Foundation/Foundation.h>
>
> int main (int argc, const char * argv[]) {
>    NSAutoreleasePool * pool = [[NSAutoreleasePool alloc] init];
>
>    // insert code here...
>    NSLog(@"Hello, World!");
>    [pool release];
>    return 0;
> }
>
> ----
>
> $ llvm-gcc -c -emit-llvm SimpleFoundation.m -o SimpleFoundation.bc
> $ llc SimpleFoundation.bc -o SimpleFoundation.s
> $ gcc /System/Library/Frameworks/Foundation.framework/Foundation
> SimpleFoundation.s -o SimpleFoundation.exe
> $ ./SimpleFoundation.exe
>
> 2007-07-19 17:42:32.667 SimpleFoundation.exe[2535] Hello, World!

yay :)

> $ lli -load=/System/Library/Frameworks/Foundation.framework/Foundation
> SimpleFoundation.bc
>
> Segmentation fault
>
> $ lli -force-interpreter
> -load=/System/Library/Frameworks/Foundation.framework/Foundation
> SimpleFoundation.bc
>
> Could not resolve external global address: .objc_class_name_NSAutoreleasePool
> Abort trap
>
> $ nm /System/Library/Frameworks/Foundation.framework/Foundation |
> grep .objc_class_name_NSAutoreleasePool
>
> 00000000 A .objc_class_name_NSAutoreleasePool

Ok, as you figured out, you do need to tell lli explicitly what frameworks 
to load.  Once you have that, you are hitting another problem. 
Specifically, the JIT::getPointerToNamedFunction method in 
lib/ExecutionEngine/JIT/Intercept.cpp just does a dlsym on missing 
symbols.  If dlsym returns null, you get the error message.

The problem here is that .objc_class_name_* are special symbols that are 
used by the objc linker support and they have magic meaning.  This itself 
isn't a problem, the problem is that they are absolute symbols (which is 
why nm prints 'A' for the symbol) and their absolute value is 0.  When 
dlsym correctly returns the address of this symbol, it returns a null 
pointer (which is the address of the symbol) and lli aborts because it 
thinks dlsym returned failure.

After consulting with our dynamic linker guru, I don't think there is a 
wonderful clean way to do this.  I suggest adding a memcmp to the error 
path in getPointerToNamedFunction that checks to see if the symbol starts 
with ".objc_class_name_".  If so, getPointerToNamedFunction should return 
null without aborting.  There may be one or two other prefixes you will 
have to add, for selectors or categories.

Once this is done, your example above should work.  However, when you move 
on to more interesting examples, you'll probably hit other issues.  For 
example, the objc runtime needs to be informed of any new classes that are 
added to an address space.  I think the runtime has API calls that are 
used to do this, but the LLVM JIT currently doesn't know how to do any of 
them.

If you're interested in investigating this and adding support to LLVM, it 
would be greatly appreciated.

-Chris

-- 
http://nondot.org/sabre/
http://llvm.org/



More information about the llvm-dev mailing list