Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Why is it impossible to hide symbols from Objective-C object files?

I am writing a small dynamic library that uses Objective-C and exposes C-linkage functions to Unity (it's a native plugin).

Even though my compiler settings has Symbols Hidden by Default set to Yes, and I am using __attribute__((visibility("default"))) on the function declarations I want to expose, even static symbols (both functions and global variables) appear in the output library.

I have recreated a test Xcode project, which initially contained a C file

file.h:

#pragma once

extern __attribute__((visibility("default"))) void not_hidden();

file.c:

#include "file.h"
#include <stdio.h>

static void hidden()
{
    printf("I'm hidden\n");
}

void not_hidden()
{
    printf("I'm not hidden\n");
    hidden();
}

and this works as advertised:

$ nm libHiddenSymbolTest.dylib 
0000000000000f40 T _not_hidden
                 U _printf
                 U dyld_stub_binder

However as soon as I add an Objective-C file with similar functions (not_hidden2(), etc), then all static symbols are likewise exposed:

$ nm libHiddenSymbolTest.dylib 
                 U _CFStringGetCStringPtr
                 U _NSLog
00000000000054d0 s _OBJC_METACLASS_$___ARCLite__
                 U __Block_copy
                 U __DefaultRuneLocale
0000000000005710 b __ZGVZL18add_image_hook_ARCPK11mach_headerlE7patches
0000000000005830 b __ZGVZL22add_image_hook_swiftV1PK11mach_headerlE7patches
0000000000005640 b __ZGVZL30add_image_hook_autoreleasepoolPK11mach_headerlE7patches
0000000000004160 s __ZL11_class_name
00000000000039a4 t __ZL12cxxConstructP11objc_object
00000000000055d0 d __ZL12demangleLock
000000000000377a t __ZL13demangledNamePKcb
0000000000002ab3 t __ZL13replaceMethodP10objc_classP13objc_selectorPFP11objc_objectS4_S2_zEPS6_
0000000000005748 b __ZL14NSString_class
00000000000035b0 t __ZL14initialize_impP11objc_objectP13objc_selector
0000000000001aa2 t __ZL15__ARCLite__loadv
0000000000003927 t __ZL16scanMangledFieldRPKcS0_S1_Ri
00000000000041a8 s __ZL17_load_method_name
00000000000043d0 s __ZL17_load_method_type
0000000000003461 t __ZL17transcribeMethodsP10objc_classP15glue_class_ro_t
00000000000022b9 t __ZL18add_image_hook_ARCPK11mach_headerl
00000000000035b6 t __ZL18allocateMaybeSwiftP18glue_swift_class_tm
0000000000001f7f t __ZL19patch_lazy_pointersPK11mach_headerP7patch_tm
00000000000034e5 t __ZL19transcribeProtocolsP10objc_classP15glue_class_ro_t
00000000000039d4 t __ZL20fixStringForCoreDataP11objc_object
0000000000003530 t __ZL20transcribePropertiesP10objc_classP15glue_class_ro_t
0000000000002785 t __ZL21__arclite_objc_retainP11objc_object
00000000000025e3 t __ZL21__arclite_object_copyP11objc_objectm
0000000000005740 b __ZL22NSConstantString_class
00000000000027a1 t __ZL22__arclite_objc_releaseP11objc_object
000000000000288f t __ZL22add_image_hook_swiftV1PK11mach_headerl
0000000000003646 t __ZL22copySwiftV1MangledNamePKcb
0000000000005870 b __ZL22original_class_getName
0000000000005848 b __ZL22original_objc_getClass
0000000000005610 b __ZL23NSAutoreleasePool_class
00000000000033dc t __ZL23__arclite_class_getNameP10objc_class
0000000000003230 t __ZL23__arclite_objc_getClassPKc
00000000000054f8 s __ZL24OBJC_CLASS_$___ARCLite__
000000000000248c t __ZL24__arclite_object_setIvarP11objc_objectP9objc_ivarS0_
0000000000005738 b __ZL25NSMutableDictionary_class
0000000000005868 b __ZL25original_objc_getProtocol
0000000000005860 b __ZL25original_objc_lookUpClass
0000000000005878 b __ZL25original_protocol_getName
00000000000027b3 t __ZL26__arclite_objc_autoreleaseP11objc_object
0000000000003384 t __ZL26__arclite_objc_getProtocolPKc
000000000000332f t __ZL26__arclite_objc_lookUpClassPKc
0000000000002797 t __ZL26__arclite_objc_retainBlockP11objc_object
000000000000283f t __ZL26__arclite_objc_storeStrongPP11objc_objectS0_
00000000000033f1 t __ZL26__arclite_protocol_getNameP8Protocol
0000000000005850 b __ZL26original_objc_getMetaClass
00000000000052c8 s __ZL27OBJC_CLASS_RO_$___ARCLite__
0000000000003285 t __ZL27__arclite_objc_getMetaClassPKc
0000000000005758 b __ZL27original_NSKKMS_indexForKey
0000000000002b9a t __ZL28__arclite_NSKKMS_indexForKeyP11objc_objectP13objc_selectorS0_
0000000000002df0 t __ZL28__arclite_objc_readClassPairP10objc_classPK15objc_image_info
0000000000005760 b __ZL28original_NSKKsD_objectForKey
0000000000002bec t __ZL29__arclite_NSKKsD_objectForKeyP11objc_objectP13objc_selectorS0_
0000000000005720 b __ZL29original_NSManagedObject_init
0000000000005718 b __ZL30NSUndoManagerProxy_targetClass
0000000000002ae6 t __ZL30__arclite_NSManagedObject_initP11objc_objectP13objc_selector
0000000000001ecb t __ZL30add_image_hook_autoreleasepoolPK11mach_headerl
000000000000399e t __ZL30arclite_uninitialized_functionv
0000000000005858 b __ZL30original_objc_getRequiredClass
0000000000005280 s __ZL31OBJC_METACLASS_RO_$___ARCLite__
00000000000032da t __ZL31__arclite_objc_getRequiredClassPKc
0000000000005838 b __ZL31original_objc_allocateClassPair
0000000000005840 b __ZL31original_object_getIndexedIvars
0000000000005310 s __ZL32OBJC_$_CLASS_METHODS___ARCLite__
000000000000313d t __ZL32__arclite_objc_allocateClassPairP10objc_classPKcm
00000000000027c5 t __ZL32__arclite_objc_retainAutoreleaseP11objc_object
00000000000031de t __ZL32__arclite_object_getIndexedIvarsP11objc_object
0000000000005770 b __ZL32original_NSKKsD_setObject_forKey
0000000000002c92 t __ZL33__arclite_NSKKsD_setObject_forKeyP11objc_objectP13objc_selectorS0_S0_
0000000000001f6d t __ZL33__arclite_objc_autoreleasePoolPopPv
0000000000001f54 t __ZL34__arclite_objc_autoreleasePoolPushv
0000000000005768 b __ZL34original_NSKKsD_removeObjectForKey
0000000000002c3e t __ZL35__arclite_NSKKsD_removeObjectForKeyP11objc_objectP13objc_selectorS0_
0000000000005730 b __ZL35original_NSManagedObject_allocBatch
0000000000002b0c t __ZL36__arclite_NSManagedObject_allocBatchP11objc_objectP13objc_selectorPS0_S0_j
0000000000002434 t __ZL36__arclite_object_setInstanceVariableP11objc_objectPKcPv
0000000000005750 b __ZL36original_NSKKMS_fastIndexForKnownKey
0000000000005880 b __ZL36original_objc_copyClassNamesForImage
0000000000002b48 t __ZL37__arclite_NSKKMS_fastIndexForKnownKeyP11objc_objectP13objc_selectorS0_
00000000000027f0 t __ZL37__arclite_objc_autoreleaseReturnValueP11objc_object
0000000000003409 t __ZL37__arclite_objc_copyClassNamesForImagePKcPj
0000000000005778 b __ZL40original_NSKKsD_addEntriesFromDictionary
0000000000005728 b __ZL40original_NSManagedObject_allocWithEntity
0000000000002cfb t __ZL41__arclite_NSKKsD_addEntriesFromDictionaryP11objc_objectP13objc_selectorP12NSDictionary
0000000000002af9 t __ZL41__arclite_NSManagedObject_allocWithEntityP11objc_objectP13objc_selectorS0_
00000000000021e7 t __ZL42__arclite_NSArray_objectAtIndexedSubscriptP7NSArrayP13objc_selectorm
0000000000002a7a t __ZL42__arclite_NSUndoManagerProxy_isKindOfClassP11objc_objectP13objc_selectorP10objc_class
0000000000002802 t __ZL43__arclite_objc_retainAutoreleaseReturnValueP11objc_object
000000000000282d t __ZL44__arclite_objc_retainAutoreleasedReturnValueP11objc_object
000000000000225b t __ZL46__arclite_NSDictionary_objectForKeyedSubscriptP12NSDictionaryP13objc_selectorP11objc_object
000000000000226d t __ZL47__arclite_NSOrderedSet_objectAtIndexedSubscriptP12NSOrderedSetP13objc_selectorm
00000000000021f9 t __ZL53__arclite_NSMutableArray_setObject_atIndexedSubscriptP14NSMutableArrayP13objc_selectorP11objc_objectm
0000000000002291 t __ZL58__arclite_NSMutableDictionary__setObject_forKeyedSubscriptP19NSMutableDictionaryP13objc_selectorP11objc_objectS4_
000000000000227f t __ZL58__arclite_NSMutableOrderedSet_setObject_atIndexedSubscriptP19NSMutableOrderedSetP13objc_selectorP11objc_objectm
0000000000005888 b __ZL9Demangled
0000000000005650 b __ZZL18add_image_hook_ARCPK11mach_headerlE7patches
0000000000005780 b __ZZL22add_image_hook_swiftV1PK11mach_headerlE7patches
0000000000005620 b __ZZL30add_image_hook_autoreleasepoolPK11mach_headerlE7patches
                 U ___CFConstantStringClassReference
                 U ___stack_chk_fail
                 U ___stack_chk_guard
                 U __dyld_register_func_for_add_image
0000000000005260 s __non_lazy_classes
                 U __objc_empty_cache
                 U __objc_empty_vtable
                 U _asprintf
                 U _bzero
                 U _calloc
                 U _class_addMethod
                 U _class_addProperty
                 U _class_addProtocol
                 U _class_getInstanceMethod
                 U _class_getInstanceSize
                 U _class_getInstanceVariable
                 U _class_getIvarLayout
                 U _class_getName
                 U _class_getSuperclass
                 U _class_isMetaClass
                 U _class_replaceMethod
                 U _class_respondsToSelector
                 U _free
                 U _hash_create
                 U _hash_search
0000000000001a30 t _hidden
0000000000001a70 t _hidden2
                 U _ivar_getName
                 U _ivar_getOffset
                 U _kCFCoreFoundationVersionNumber
                 U _malloc
                 U _memcmp
                 U _memcpy
                 U _method_setImplementation
0000000000001a00 T _not_hidden
0000000000001a50 T _not_hidden2
                 U _objc_allocateClassPair
                 U _objc_autoreleasePoolPush
                 U _objc_collectingEnabled
                 U _objc_constructInstance
                 U _objc_copyClassNamesForImage
                 U _objc_getClass
                 U _objc_getMetaClass
                 U _objc_getProtocol
                 U _objc_getRequiredClass
                 U _objc_initializeClassPair
                 U _objc_lookUpClass
                 U _objc_msgSend
                 U _objc_readClassPair
                 U _objc_registerClassPair
                 U _objc_retain
0000000000001a87 T _objc_retainedObject
0000000000001a90 T _objc_unretainedObject
0000000000001a99 T _objc_unretainedPointer
                 U _object_getClass
                 U _object_getIndexedIvars
                 U _object_getIvar
                 U _object_setIvar
                 U _printf
                 U _property_copyAttributeList
                 U _protocol_getMethodDescription
                 U _protocol_getName
                 U _pthread_mutex_lock
                 U _pthread_mutex_unlock
                 U _sel_getUid
                 U _strcmp
                 U _strlen
                 U _strncmp
                 U dyld_stub_binder

Note that I have left the various strip symbols settings to their default, and this appears to be OK for C-file symbols as shown in the first nm output, above.

Can anyone explain why that is, and perhaps suggest a way to hide the Objective-C symbols I don't want exposed?

Update: I am using Xcode 7.0.1 on OSX 10.11.0.

Update #2 (more experimentation):

  1. Including a .m file in the project causes Xcode to stop passing -fvisibility=hidden during compilation of the .c file, thereby ignoring the Symbols Hidden by Default build setting. To repeat; before adding the .m this was being passed to the compiler.
  2. Setting the Exported Symbols File to a file containing _not_hidden and _not_hidden2 has no effect whatsoever.

It seems to me that ignoring Symbols Hidden by Default is the root cause of the issue so I experimented with explicitly setting __attribute__((visibility("hidden"/"default"))) (via a preprocessor macro) on every single function and variable and it has no effect either. So that seems to implicate the linker.

like image 807
Droppy Avatar asked Oct 08 '15 16:10

Droppy


Video Answer


2 Answers

There are several reasons why you are still seeing a bunch of symbols in your dylib:

1. The strip mode you have set (or don't) isn't getting everything it's capable of.

(Try adjusting the strip styles in the build settings, generally removing debugging symbols is fine, however, I've bumped it up to Non-Global Symbols for this purpose, which is likely about as far as you can take it. Your dylib likely won't compile if you decide to strip all symbols, and it would essentially render it unusable at that point)

enter image description here

2. Some Objective-C symbols are absolutely required.

(These include any of the objc variety, and others such as class, property, object, etc. since they are all supporting the runtime, and yes there can still be quite a few present)

3. You are possibly looking at the debug version of your dylib and not the release version.

(Make sure you are looking at the release version of your dylib. That would be Product > Archive > Export. It should then be nicely stripped of most of the symbols that are not actually being used.


You might need to play around with the strip settings a bit, although just using the settings that I've shown above resulted in approximately 100+ fewer symbols than currently show in your dump. It's really not bad to have symbols included in your file, in fact if there's ever a problem then it's all the more helpful. It's understandable though if you want to remove irrelevant or unused symbols that just clutter things up.

like image 70
l'L'l Avatar answered Oct 06 '22 07:10

l'L'l


OK, stripping the non-global symbols does solve the issue, however I was unable to set the correct sequence in the Deployment section of the Build Settings (I tried many different combos).

The only way I could force the linker to remove non-global symbols was to add this to the Other Linker Flags:

-Xlinker -x
like image 39
Droppy Avatar answered Oct 06 '22 07:10

Droppy