Load named unexported symbols with dlsym? - dlsym

Is it possible to load a named unexported symbol from a framework using dlsym?
The symbol I'm trying to import has a name by which it is referred to within the framework. It is a function I need to call.
I'm trying to do it the usual dlopen + dlsym way, but when I try to load a symbol that isn't exported, dlsym returns a NULL pointer.

dlsym can only load functions that are listed in the symbol table. You can list the symbol table by running nm on the framework in question.
You can verify this in the dyld source:
ImageLoaderMachOClassic::findExportedSymbol is the internal implementation of dlsym, it simply binary searches the symbol table:
And ImageLoaderMachO::parseLoadCmds loads the symbol table from the load commands in the Mach header:

Related

How can I keep a symbol during gcc strip?

Using arm-linux-gnueabi-gcc, I'm working with a shared object that has an undefined reference to "main". I'm using dlopen() to open this library. However, when my program is compiled with "-Wl,-s", the symbol main is removed, which causes dlopen() to fail with an undefined symbol "main".
In gcc, is there any way I can perform a strip, but keep the symbol main?
Edit: even better, can I put just the symbol "main" in the dynamic section (similar to -rdynamic)?
The shared object with an undefined reference to main appears to use the dynamic symbol table to search for the reference to "main". So, there are two options here:
Compile with "-Wl,-rdynamic". This will put all of the symbols into the dynamic symbol table. This works, but it results in a lot of extra symbols being put in there, too.
Compile with "-Wl,--dynamic-list=[path to my list file]". Then list "main" in the dynamic file to retain only main in the dynamic symbols table. This has the drawback that all dynamic references must now be managed, but for simple programs, this is adequate.
Example of (2):
Invocation:
arm-linux-gnueabi-gcc -fPIC mycode.c -Wl,-s,--dynamic-list=./dynamic_symbols.txt
dynamic_symbols.txt:
{ main; };

nm symbol output t vs T in a shared so library

I have added a new function (fuse_lowlevel_notify_inval_directory) in user space fuse library.
The compilation and creation of libfuse.so is finished without error.
But when my application tries to use this new function, the linker is throwing error: undefined reference to `fuse_lowlevel_notify_inval_directory'
collect2: ld returned 1 exit status
When I checked with nm
nm ../libfuse.so | grep inval
00000000000154ed T fuse_invalidate
**000000000001e142 t fuse_lowlevel_notify_inval_directory**
000000000001e26c T fuse_lowlevel_notify_inval_entry
000000000001e1cb T fuse_lowlevel_notify_inval_inode
T/t means the symbol is present in text section. if uppercase, the symbol is global (external). I suspect this is the issue. The new added function is showing lowercase t while other older functions are having upper case T. Any idea about what I might be doing wrong?
Any idea about what I might be doing wrong?
The t function is indeed local to the library. This could happen due to a number or reasons. The most likely ones are:
You declared the function static, or
You compiled the library with -fvisibility=hidden and did not have __attribute__((visibility("default"))) on the function, or
You linked this library with a linker version script (i.e. with --version-script=libfoo.version flag) that hides all functions, except those which are explicitly exported, and you didn't add your function to that list.
See this example of using --version-script to limit symbol visibility.

Exported variable vs exported function in a DLL

How to know if the exported symbol from a dll is actually variable or a function ?
One way may be to look whether the destination address of the symbol resides in the .code section or not.
Another method could be to check the memory protection attributes of the selected section.
But all these methods seem to be unreliable.
What is the best way ?

dlopen and dylib : main application and dylib address space

My main application statically links to a static library A with a function ABC and my dynamic library xyz.dylib also statically links to the same static library A which has the same function ABC. The function ABC uses a globally defined variable.
Now when the main application Loads xyz.dylib using dlopen on runtime. The initializer gets called where i have called ABC function. This function ABC and uses the global variable from main application address space.
On Osx, functions which are inline the dylib linker will use the first one that is used. So for example, if an inline function is used in your main executable first, and then used in the loaded dylib, it will use the one in the main executable.
This is normally fine, unless your inline makes reference to a global symbol, in which case you are now be using one if your globals for both the dylib, and your executable.
Again this is usually fine, since the same version is used consistently.
The problem happens when you have 2 inline functions that reference a global that is in both executable and dylib, and one function gets used first in the executable, and another one used first in the dylib. Then you have a mismatched pair. For example:
class MagicAlloc
{
void* Alloc() { return gAlloc.get(); }
void Free( void* v ) { gAlloc.free( v ); }
static RealAllocator gAlloc;
};
Suppose you call MagicAlloc::Alloc in the executable, then call it in the dylib, now for all allocations in both you will use the gAlloc in the executable. Then the first call to MagicAlloc::Free happens in the dylib. Then you will try to free something allocated in the binary on the globals from the dylib.
There are two solutions:
Don't use inlines to reference globals/statics. Move the global structure, and the function definitions into the same translation unit ( object file ). Mark the globals "static" so they aren't even visible outside the TLU. Now your functions will be resolved statically in the link step, and bound to the right global.
Hide all the symbols in the executable except the plugin api. Link as normal, but when linking the binary itself pass the following to the linker:
-Wl,-exported_symbols_list,export_file
Where export file is a list of link symbols that should be exported. E.g. you will need to at least have "_main" in that file. Now when your dylib runs it won't be able to dynamically link to the wrong inlines, because they won't be in the dynamic symbol table. The second solution is also more secure, since a malicious plugin won't be able to access globals as easily.

OSX 10.5 Leopard Symbol Mangling with $non_lazy_ptr

Why does Leopard mangle some symbols with $non_lazy_ptr? More importantly what is the best method to fix undefined symbol errors because a symbol has been mangled with $non_lazy_ptr?
From: Developer Connection - Indirect Addressing
Indirect addressing is the name of the code generation technique that allows symbols defined in one file to be referenced from another file, without requiring the referencing file to have explicit knowledge of the layout of the file that defines the symbol. Therefore, the defining file can be modified independently of the referencing file. Indirect addressing minimizes the number of locations that must be modified by the dynamic linker, which facilitates code sharing and improves performance.
When a file uses data that is defined in another file, it creates symbol references. A symbol reference identifies the file from which a symbol is imported and the referenced symbol. There are two types of symbol references: nonlazy and lazy.
Nonlazy symbol references are resolved (bound to their definitions) by the dynamic linker when a module is loaded.
A nonlazy symbol reference is essentially a symbol pointer—a pointer-sized piece of data. The compiler generates nonlazy symbol references for data symbols or function addresses.
Lazy symbol references are resolved by the dynamic linker the first time they are used (not at load time). Subsequent calls to the referenced symbol jump directly to the symbol’s definition.
Lazy symbol references are made up of a symbol pointer and a symbol stub, a small amount of code that directly dereferences and jumps through the symbol pointer. The compiler generates lazy symbol references when it encounters a call to a function defined in another file.
In human-speak: the compiler generates stubs with $non_lazy_ptr appended to them to speed up linking. You're probably seeing that function Foo referenced from _Foo$non_lazy_ptr is undefined, or something like that - these are not the same thing. Make sure that the symbol is actually declared and exported in the object files/libraries you're linking your app to. At least that was my problem, I also thought it's a weird linker thing until I found that my problem was elsewhere - there are several other possible causes found on Google.
ranlib -c libwhatever.a
is a solid fix for the issue. I had the same problem when building the PJSIP library for iOS. This library sort-of uses an autoconf based make system, but needs a little tweaking to various files to make everything alright for iOS. In the process of doing that I managed to remove the ranlib line in the rule for libraries and then started getting an error in the link of my project about _PJ_NO_MEMORY_EXCEPTION referenced from _PJ_NO_MEMORY_EXCEPTION$non_lazy_ptr being undefined.
Adding the ranlib line back to the library file solved it. Now my full entry for LIBS in rules.mak is
$(LIB): $(OBJDIRS) $(OBJS) $($(APP)_EXTRA_DEP)
if test ! -d $(LIBDIR); then $(subst ##,$(subst /,$(HOST_PSEP),$(LIBDIR)),$(HOST_MKDIR)); fi
$(LIBTOOL) -o $(LIB) $(OBJS)
$(RANLIB) -c $(LIB)
Hope this helps others as well trying to use general UNIX configured external libraries with iPhone or iOS.
If someone else stumbles the same problem I had:
Had a extern NSString* const someString; in the header file, but forgot to put it the implementation file. as NSString* const someString=#"someString";
This solved it.
ranlib -c on your library file fixes the problem

Resources