2
votes

I've built a 32-bit dylib for OS X with Delphi XE2 Upd. 3. It's install-name uses @rpath. All exports start with an underscore, verified with otool. The exports use "cdecl" calling convention in Delphi.

I cannot get this dylib to work with a 32bit host application in Xcode 4.3 running on OS X 10.7.3. When I run the test project from within Xcode, it stops with the call to the lib and dyld_start in the call stack.

enter image description here

When I run this app from Finder (from the Xcode folder within the user-library), I get the Image Not Found error from dyld.

I've already added a copy build phase, which copies the dylib (and libcgunwind.1.0.dylib which it requires) into the Products directory. I've also set Runpath Search Paths to @executable_path or @loader_path, all to no avail.

The method is imported via

extern int TestLib(int AInt);

The library is as minimal as it can get and just contains this unit:

unit LibTestExports;

uses
  System.Classes,
  System.SysUtils;

function _TestLib(AInt: Integer): Integer; export; cdecl;
begin
  Result:= AInt + 2;
end;

exports
  _TestLib;

end.

I'm out of ideas on what is causing this and how I can get this to work.

The Xcode project and the libs can be found here: http://dl.dropbox.com/u/17403534/CAS4LibTest.zip

UPDATE: This problem seems to be Lion-specific! It works fine in Snow Leopard 10.6.4 using Xcode 4.2. (Xcode 4.2 on Lion results in the same problem)

The same dylib also works just fine under Lion when used by a FireMonkey application (the methods are statically imported using external 'libName').

Running the same app under Lion, that works fine under SnowLeopard, I get a crash report containing the following call stack:

0   ???                             0x0013317c 0 + 1257852
1   libCAS4.dylib                   0x00010b5c @DbgEvalFrame + 1648
2   libCAS4.dylib                   0x00010e1a @DbgEvalFrame + 2350
3   dyld                            0x8fe55203 ImageLoaderMachO::doModInitFunctions(ImageLoader::LinkContext const&) + 251
4   dyld                            0x8fe54d68 ImageLoaderMachO::doInitialization(ImageLoader::LinkContext const&) + 64
5   dyld                            0x8fe522c8 ImageLoader::recursiveInitialization(ImageLoader::LinkContext const&, unsigned int, ImageLoader::InitializerTimingList&) + 256
6   dyld                            0x8fe5225e ImageLoader::recursiveInitialization(ImageLoader::LinkContext const&, unsigned int, ImageLoader::InitializerTimingList&) + 150
7   dyld                            0x8fe53268 ImageLoader::runInitializers(ImageLoader::LinkContext const&, ImageLoader::InitializerTimingList&) + 62
8   dyld                            0x8fe47694 dyld::initializeMainExecutable() + 214
9   dyld                            0x8fe4bf99 dyld::_main(macho_header const*, unsigned long, int, char const**, char const**, char const**) + 2238
10  dyld                            0x8fe452ef dyldbootstrap::start(macho_header const*, int, char const**, long, macho_header const*) + 637
11  dyld                            0x8fe45063 _dyld_start + 51

Workaround: Embarcadero support now came back with a workaround, which fixes the issue for me: in a local copy of System.Classes change the declaration of GlobalNameSpace: IReadWriteSync to the appropriate class as used in the initialization section.

1
nm: object: libLibTest.dylib malformed object (indirect table at offset 509728 with a size of 576, overlaps section contents at offset 507904 with a size of 67082) ... is the test library valid? - Petesh
I would hope the library is valid, but I don't know for sure. If it's not, that would mean Delphi XE2 is severly broken, since this is the most basic code turned into a library. Actually I've also noticed that nm thought the library is invalid but then saw that otool outputs the exports just fine. - msohn
Bear in mind that nm, otool and dyld use different code to read the relevant elements in the file. nm's complaint may be the reason for the failure in the dyld invocation. I used IDA to disassemble the TestLib call, and it looks like it takes an int * as a parameter, not an int. This would have a side-effect of causing an access violation when invoked; but it looks like the error happens before that (at the library load time) - Petesh
Thanks for looking into this. Could you confirm that the copy files and the Runtime Search Path in the Xcode project are correct? When why do I get the Image Not Found when running from Finder? The Delphi code definitely takes an int not a int* as a parameter, and also returns an int. Is it possible that another dependent library is missing? - msohn
The copy files and Runtime Search Path settings are correct - when I remove either, the program fails event to load. I modified the libLibTest to lazy load, and the crash happens while loading the library in question. Can you update the question with the function declaration/definition in the test library (just the signature; the code should not matter) - Petesh

1 Answers

2
votes

The library you're building has an implicit dependency on bplrtl160.dylib, which you'll need to bundle with the app - You should make sure that the library is built using run-time packages.

There is some form of initialization magic that happens when you build an executable with Delphi XE2 that doesn't happen when you build the application under xcode, which is causing the problem; probably some initialization code that is linked into the app that isn't linked in when it's made as a library.

The actual exception you are getting is in:

@$xp$30System@Sysutils@IReadWriteSync

which is happening at bplrtl160.dylib load time (i.e. you don't even get to interact with the library by this point). This is an interface class which should be initialized at application load time.

If you remove the System.SysUtils, System.Classes entries from the uses clause of the library file, then it will actually load the library; but it means that any library that you build from XE2 can't use the classes and sysutils code; which makes it a little bit less than suitable for use.

As for the fix; I don't know. There may be no fix at all.