OK, I know there have been other posts about how you can't actually strip Objective-C symbols from an OS X binary because they're necessary for Obj-C to work at all, but my case is a bit different.
I have a single binary which is a bundle. It is intended to be used as either a VST plugin, or an AudioUnit plugin. The idea is that the binary contains all the entry points for both formats, and you just compile it once, and then name one copy with ".vst" for the VST version, and ".component" for the AU version. (This is using the JUCE framework BTW.)
The problem is that for the AU side, you must export an Obj-C class for creating the Cocoa UI view. On the VST side, this class will never be used. But if you have a host like Ableton Live which allows you to simultaneously load both AU and VST versions of the same plugin, now we run into the typical Obj-C namespace collision issue.
On the VST side, that particular Obj-C class will never get used. So what I'd like to do is to strip those Obj-C classes from the resulting binary using "strip". This still maintains the advantage of just compiling everything once for both formats.
Anyway, I've tried using "strip -R stripfile.txt <path to binary>", where stripfile.txt contains the symbols I want to strip, but it always fails saying that the symbols can't be found in the binary. I've tried mangling the names in the strip file, but that doesn't help (or I'm doing it wrong).
Here are the relevant symbols that I want to strip, as output by "nm -m":
000000000003bb00 (__TEXT,__text) non-external -[JuceDemoProjectAU description]
000000000003bb60 (__TEXT,__text) non-external -[JuceDemoProjectAU interfaceVersion]
000000000003ba00 (__TEXT,__text) non-external -[JuceDemoProjectAU uiViewForAudioUnit:withSize:]
0000000000b02398 (__DATA,__objc_data) external _OBJC_CLASS_$_JuceDemoProjectAU
0000000000b023c0 (__DATA,__objc_data) external _OBJC_METACLASS_$_JuceDemoProjectAU
Any ideas?
BTW, I have subsequently been able to dynamically register the class in question (using a unique name), which also solves the problem. However, if I could get strip working, I could potentially deploy a solution for already existing binaries in the field.
You can not just simply strip a class from a binary. What you can do however is to trick the Objective-C runtime into believing your plugin does not contain any Objective-C code. Just change __objc_imageinfo into __objc_imageinfX for example in your VST plugin binary. You can do it easily with perl:
perl -pi -e 's/__objc_imageinfo/__objc_imageinfX/g' <path to binary>
After patching the VST plugin, all the Objective-C initialization will be bypassed and you won’t see this error message: Class JuceDemoProjectAU is implemented in both …/VSTPlugin and …/AUPlugin. One of the two will be used. Which one is undefined.
Beware, you should really not use this trick! The appropriate solution to your problem is either to compile two different version of your plugin or to register classes dynamically as others suggested.
There was a thread about something similar to this on the coreaudio-list last year: Collision between Cocoa classes for AU and VST plugins.
The solution offered was to register the classes dynamically which is what you say you already have working. If there was a way to strip the symbols like you wanted, I'm sure these guys would have known about it.
Related
If my static library is using AFNetworking and a client project is also using it, it seems like constants defined in AFNetworking will collide, causing the client project not to be able to build (duplicate symbol error). How are things like this resolved usually? What should framework creator do to avoid that?
Try the approach in this link:
http://blog.sigmapoint.pl/avoiding-dependency-collisions-in-ios-static-library-managed-by-cocoapods/
which he describes as:
Build library with prefixed symbols - in my opinion the best way. We
would like to add a prefix to all of the symbols in final .a file so
that e.g. AFHTTPSessionManager becomes
SIGMAPOINT_AFHTTPSessionManager. Your version of dependency is not
connected to version used by developer and no collisions occurs. The
only disadvantage is bigger output file because when someone uses the
same library the final file will contain the same symbols: once
prefixed and once not prefixed. But the whole build process will work
smooth and without errors. This is the solution we will investigate
further in this article.
This tool may help
https://github.com/cocoapods/cocoapods-packager
I want to add a prefix to every symbol in an elf object file, how do you do that using Linux (eg debian)?
I need the debug information to still work (ie, gdb can still debug effectively albeit using the new names for all the symbols).
The elf object is relocatable.
A solution for a non-relocatable object would also be welcome.
A solution for which code-coverage stats continues to work would also be welcome but is not necessary.
I don't know of any canned way to do this.
I think it could be done by rewriting the ELF symbol table and the DWARF information as well. This is not trivial, though perhaps you could implement it using the various libraries in elfutils.
I am learning Objective-C, but can't understand one thing with the frameworks. Each framework in objective-C contains header files which contain only #interface part. That means that header files only declare difference methods and do not implement them. Is this implementation part hidden in the frameworks or something, because I can't get how it works.
Thank you in advance for your answers!
Is this implementation part hidden in the frameworks or something
Well, sort of. It's compiled (the actual source code is not present neither in the SDK nor in the OS) and only the binary executable code is contained within the dynamic library that resides inside the framework.
It is still possible to use them (i. e. link against them), obviously (see this for an explanation), but you cannot edit the source code. In theory, you could try binpatching them (i. e. disassembling, analyzing and editing the executable file using a hex editor or something), but that's neither recommended (you can screw up your entire system if you do one slight thing wrong), nor easy.
Just leave alone the Apple policy, just talking about the Objective-C language only,
Assume that my programme calling a .a library. Is this possible to grep the .a from the
internet, and run a newer version of .a instead of old .a?
Thanks.
Not for statically linked libraries (.a), at least with any level of sanity. You can certainly do it with dynamically loaded libraries (.so); it's one of the normal use cases. Have a look at dlopen, dlclose and dlsym from the dynamic loader (https://developer.apple.com/library/mac/#documentation/DeveloperTools/Reference/MachOReference/Reference/reference.html).
This is not just iOS, but OS X apps (and probably other Unixes in general)
Static libraries (.a files) cannot be replaced while the program is running because they are part of the application binary. The application binary is mapped into the process's address space. If you try to change any part of it, you'll almost certainly end up crashing the app.
Dynamic libraries (.so files) are replaceable in theory. However, most applications load them up once at the beginning or when first needed and then they become part of the application's address space. I've heard that it is theoretically possible for an application to unload a dynamic library, but I've never seen it done in any real Cooca application.
Is it possible to extract a binary, to get the code that is behind the binary? With Class-dump you can see the implementation addresses, but is it possible to also see the code thats IN the implementation addresses? Is there ANY way to do it?
All your code compiles to single instructions, placed in the text section of your executable. The compiler is responsible for translating your higher level language to the processor specific instructions, which are simpler. Reverting this process would be nearly impossible, unless the code is quite simple. Some problems are ambiguity of statements, and the overall readability: local variables, for instance, will be nothing but an offset address.
If you want to read the disassembled code (the instructions of which the higher level code was compiled to) use this command in an executable:
otool -tV file
You can decompile (more accurately, disassemble) a binary and get it's assembly, but there is no way to get back the original Objective-C.
My curiosity begs me to ask why you want to do this!?
otx http://otx.osxninja.com/ is a good tool for symbolicating the otool based disassembly
It will handle both x86_64 and i386 disassembly.
and
Mach-O-Scope https://github.com/smorr/Mach-O-Scope is a a tool built on top of otx to dump it all into a sqlite3 database for browsing and annotating.
It won't give you the original source -- but it will get you pretty close providing you with the messages that are being sent around in methods.