I need to change the symbol visibility in an object file or library. For example, a particular shared object has a symbol name present, but its local so I can't bind to it (the lower t indicates local in the TEXT section):
$ nm /usr/local/ssl/lib/libcrypto.so | grep -i OPENSSL_cpuid_setup
00000000000c3f80 t OPENSSL_cpuid_setup
000000000008a360 t fips_openssl_cpuid_setup
The same symbol is present in the archive, but the archive not being used in this project (the upper T indicates global in the TEXT section):
$ nm /usr/local/ssl/lib/libcrypto.a | grep -i OPENSSL_cpuid_setup
0000000000000310 T OPENSSL_cpuid_setup
000000000000f8e0 T fips_openssl_cpuid_setup
I'd like the visibility of OPENSSL_cpuid_setup to be global rather than local.
Is there a way to change the symbol visibility in a object file or library? I've been through Binutil tools, and it does not look like there's a suitable tool.
And for completeness, the 'easiest' methods are not available because the source code is sequestered and cannot be changed. The easiest methods include (1) removing static from the declaration; and (2) using GCC's visibility attributes.
You could try (untested) objcopy with the --globalize-symbol option. However, this is only going to work with the archive, not the dynamic library, as you can modify the normal symbol table and not the (hashed) dynamic symbol table.
A disgusting hack would be to determine the offset of the routine from a global (using objdump and writing it to a file from your makefile), then create a function pointer, then jump to that (yuck).
Related
I am trying to create an executable with .o ,.so, .a files.
Here is my build command:-
pkgs/gcc/v4.8.3/bin/gcc -L/usr/X11R6/lib -O2 -DUSE_FLEX -Wall -Wno-char-subscripts -fPIC -DLINUX -DG_DISABLE_CONST_RETURNS -fno-strict-aliasing -o ../build/kl/Release/test/bin/pure.exe -L../build/kl/Release/test/modules ../build/kl/Release/test/maker/constrfunc.TCL.o ../../build/kl/Release/test/maker/pvdbprocs.TCL.o .. ../build/kl/Release/test/maker/maker/memmaker.TCL.o .. ../build/kl/Release/test/maker/modules/libdenbase.a .. ../build/kl/Release/test/maker/guibase.o -litk3.2 -litcl4.0.0 -ltk8.3 -lcdnviptcl8.4 -litclstub4.0.0 -ldenbase -lglib-2.0 -ldenbase -lX11 -ldl -lm -lviputil -lvippli -lcdsCommonMT_sh -lpthread -L/home/dlb/extlibs/arm/lib
I have libraries which have definitions of the functions at path "-L/home/dlb/extlibs/arm/lib" . Still it is throwing error below.
Error:
../build/kl/Release/test/maker/guibase.o: In function `decodeAddrList':
tree234.c:(.text+0xc): undefined reference to `ptritclStubsPtr'
tree234.c:(.text+0x20): undefined reference to `ptrlitclStubsPtr'
tree234.c:(.text+0x12c): undefined reference to `ptrlitclStubsPtr'
tree234.c:(.text+0x140): undefined reference to `ptrlitclStubsPtr'
I have the symbol in library which is at path /home/dlb/extlibs/arm/lib :-
Command:-
readelf -s libitcl4.0.0.so | grep ptrlitclStubsPtr
348: 0000000000060f10 8 OBJECT LOCAL DEFAULT 24 ptrlitclStubsPtr
Am I missing some thing here?
Note, OP has provided more info in a repost of the same question;
quote from comment by OP:
"Due to some privacy issues...I am renaming the symbols.. It was edited by me... It was typo...I just corrected it...:)"
I.e. the identifiers in the error message and the grep line and the output of the grep line have been manually altered.
It looks like the functions you're asking about are local to the file where they were defined. That is, it looks like they were explicitly intended not (and not even allowed) to be called externally.
That is, somewhere within the source for the shared library libitcl4.0.0.so probably appears a declaration like:
static tclStubs *ptrlitclStubsPtr;
That keyword static indicates that the visibility of the resulting symbol ptrlitclStubsPtr is confined to its own source file.
I infer all of this from the fact that your reported readelf output includes the line
348: 0000000000060f10 8 OBJECT LOCAL DEFAULT 24 ptrlitclStubsPtr
That flag LOCAL indicates that the symbol is local. If it were global, intended (and able) to be called externally, the flag GLOBAL would appear instead.
Why are variables made private (static) like this, so you can't use them? It's a software engineering thing, "information hiding", intended to reduce the "width" of the interface between you and a library like libitcl4. Symbols that are private are more intimately tied to the implementation decisions within libitcl4, decisions which are not supposed to be visible to, or any concern of, the callers. It's thought that, if callers were to have access to those symbols, callers would also have to know other implementation details, meaning that the author of libitcl4 would then be unable to change those implementation details without breaking (invalidating) the calling code. So to prevent that situation, the choice is usually made to make it impossible for the caller to become dependent in this way.
In this situation you basically have three paths forward:
Remove the static tags from the variable declarations in the sources to libitcl4.0.0.so. (This obviously requires that you have access to the sources to libitcl4.0.0.so, and the ability to rebuild it. It's also probably a very bad idea. As I've explained, those symbols were probably made static for a good reason.)
Add a new function within libitcl4.0.0.so which does whatever you need done, and which, by virtue of its placement within the same source file, does have access to those symbols. (This, too, requires that you have access to and the ability to rebuild ``libitcl4.0.0.so`.)
Find some other way of doing whatever you need done, using the existing public facilities of libitcl4.0.0.so.
I am trying to create a dll file using swig for an embeddedR C Program in windows environment. I am using the below commands:
C:\swigwin-3.0.12\Examples\r\Z>swig -c++ -tcl embeddedRCall.i
C:\swigwin-3.0.12\Examples\r\Z>gcc -c embeddedRCall.c -I/swigwin-3.0.12/Examples/r/Z
C:\swigwin-3.0.12\Examples\r\Z>gcc -c embeddedRCall_wrap.c -I/Tcl/include/tcl8.6 -I/swigwin-3.0.12/Examples/r/Z
C:\swigwin-3.0.12\Examples\r\Z>gcc -shared embeddedRCall.o embeddedRCall_wrap.o -o embeddedRCall.dll -L/Tcl/lib -L/R/R-3.3.2/bin/i386 -lR -lRblas -lRiconv -lRlapack -ltcl86
% load embeddedRCall
cannot find symbol "Embeddedrcall_Init"
I was able to load other example.dll files with tclsh
However I was unable to figure out the reason-- I am already using tcl 32 bit
My module file name is and module name is embeddedRcall
Am I missing something???
I am relatively new to TCL can someone please help me.
You should have an exported (extern "C") function symbol in your library called something like Embeddedrcall_Init; it is the entry point that lets Tcl install the library into a specific interpreter instance. (It has to be found explicitly because it takes an argument.) By default, the name of the function is found by munging the name of the library (strip version number, case convert, append _Init) but the determination of the name can be overridden by the optional second argument to load.
To be more exact, if the entry is actually called EmbeddedRCall_Init, you would have to load it with:
load embeddedRCall EmbeddedRCall
# The _Init suffix is fixed when loading into a standard interp
Note the case difference! (Also, we recommend using fully qualified path names to loaded libraries, as it avoids some complexities in the dlopen() system.)
Is there any way to list the files used while creating .so file? nm cannot be useful and also `readelf' also. Does some table maintain information?
readelf -s libfoobar.so | grep FILE
you cannot list the object files used to create a shared object file, since that information is not stored by default in a shared object file. A shared library is fully linked so you cannot "unarchive" it. see reference, but you can list the functions contained using this command
nm -D /usr/lib/libopenal.so.1
Copied from http://wiki.debian.org/Multiarch/LibraryPathOverview :
any directory named in the (deprecated) DT_RPATH dynamic tag of the requesting object, or, recursively, any parent object (note that DT_RPATH is ignored if DT_RUNPATH is also present)
I can't seem to find the definition of a dynamic tag anywhere.
Every dynamically linked ELF image (executable of type ET_EXEC or library of type ET_DYN) has a dynamic table (which you can see via objdump -p a.out or readelf -d a.out). Each entry in a table contains a set of Elf32_Dyn or Elf64_Dyn entries, and each entry has a d_tag and d_value members. Documentation here.
The dynamic tag is the d_tag entry, which is just an integer tag (DT_NEEDED, DT_STRTAB, etc.) describing what the d_value of this particular entry in the table represents.
Dynamic loader uses the dynamic table to load ELF image, find libraries that are needed by it (using DT_NEEDED and DT_RPATH or DT_RUNPATH entries), initialize it (using DT_INIT or DT_INIT_ARRAY), find symbols in it (DT_SYMTAB, DT_STRTAB, DT_HASH), relocate it, etc. etc.
It simply refers to the entries in the Dynamic Section (DT probably stands for Dynamic Table or something).
You can see them with the command:
$ objdump -p program
If I have two libraries, A.lib and B.lib, both of which export foo and bar, how do I tell the linker to use the symbol foo from A.lib and the symbol bar from B.lib?
You cannot. For your example you can have definitions from foo.lib or bar.lib but not both (especially if you cannot recompile the libraries and set symbol visibility so that only the symbols you want are exported). The order you link them against your application will depend on which library's definitions are used (you'll have to use the scientific method, I think the first one linked wins). Niklas Hansson's answer is a great way to do this dynamically but it seems you don't want to modify the original application, either, to dynamically pick/choose what symbols to take out of the libraries.
If you really wanted to you could mangle the symbol tables with a hex editor so that the symbols you don't want exported have different names (hacky, but it would work). I know on Linux there is a tool called objcopy that would let you do this (not sure about Windows).
You can use LIB.EXE /EXTRACT ... to extract only the object files you want to use, and link those files into your own application.
Or you may use LIB to create one new library containing the elements you need:
First, use /REMOVE on A.LIB to remove bar.obj:
LIB.EXE /OUT:ANOBAR.LIB /REMOVE:bar.obj A.LIB
Then combine A.LIB and B.LIB, and make sure to use ANOBAR.LIB as the last on the command line to ensure its foo.obj is used instead of B.LIB's:
LIB.EXE /OUT:COMBINED.LIB B.LIB ANOBAR.LIB
Details are found here: Managing a library, especially the paragraph:
You can use LIB [...] To replace a library member with a new object, specify the library containing the member object to be replaced and the file name for the new object (or the library that contains it). When an object that has the same name exists in more than one input file, LIB puts the last object specified in the LIB command into the output library. When you replace a library member, be sure to specify the new object or library after the library that contains the old object.
I didn't test the command lines given, but I've used similar ones extensively in the past.
If you are using dynamic libraries, you could use dynamic loading and pick foo from A and bar from B when loading.