How to resolve mutual references between two shared library? - c

First, I know the title of the question is not the best. Likely, these concepts are well-known. Hence, let's try to be clear now.
I have a shared library(native Java agent) which can load additional shared libraries as plugins. In short, libCore.so does at load time:
H = dlopen("libPlugin1.so", RTLD_LAZY)
routine = dlsym("registration_function", H)
routine(struct Plugin)
That part is working, my problem is in the interaction between plugins and the core.
For instance, the core has a function with the name getDataFromTag. When the plugins tries to call such a function I get the following error:
java: symbol lookup error: libplugin1.so: undefined symbol: getDataFromTag
Take into account that the problem is with native code, there is no Java-Code involved in the interaction.
Now, it seems to me that the linker is not fixing the imported symbols in libPlugin1.so when I perform the dlopen. My questions are:
Do I need to declare the imported symbols in libPlugin1.so? How?
Do I need to declare the exported symbols in libCore.so? How?
Do I have to link the plugin with a dependencies to the core? How? Isn't that weird? Sort of cyclic dependencies?
Is this relate to the option -z defs? How can use that? How it does work?
Additional points, every plugin has a function with the name registration_function. So, I cannot use RTLD_GLOBAL.

I found a solution. I don't know if it is the best. Here it goes.
Do I have to link the plugin with a dependencies to the core? How? Isn't that weird? Sort of cyclic dependencies?
That's exactly what I did. I included in plugins the following linker switches:
LDFLAGS +=-L$(PATH_TO_CORE)
# Libraries we are dependent on
LIBRARIES+=-lCore
In the core library I am using RTLD_LAZY for performance and RTLD_LOCAL to avoid symbols' redefinition.

Related

Go compile returns duplicate symbols for architecture x86_64 error when I import 2 different packages which use C package via Cgo

Here is my code:
package main
import (
kusb "github.com/karalabe/usb"
tusb "github.com/trezor/trezord-go/usb"
)
func main() {
kusb.Enumerate(0, 0)
tusb.InitHIDAPI(nil)
}
When I compile (I'm using go mod to manage the packages), it returns this error:
duplicate symbol _libusb_dev_mem_alloc in:
/var/folders/fm/1rln65d94mn45s0h5l78tdyh0000gp/T/go-link-624554542/000002.o
/var/folders/fm/1rln65d94mn45s0h5l78tdyh0000gp/T/go-link-624554542/000020.o
ld: 136 duplicate symbols for architecture x86_64
clang: error: linker command failed with exit code 1 (use -v to see invocation)
Why?
Some investigation i had:
The both packages use the same hidapi and libusb C packages in order to interact with usb devices.
Those C packages are identical, hence it defines the same functions so i think it is directly related to the error.
in trezord-go/usb, they include .C file, not the header file.
It is very counterintuitive to me because in the perspective of package users, I shouldn't need to worry about how a C package is used in the internal of the package, only the exposed types, functions and its behaviors.
Can anyone really explain what is going on here and how can I import both of them? They do different functions, eventhough they use the same C package.
From here: https://www.repustate.com/blog/go-duplicate-symbols-for-architecture-x86_64/
"What does this mean? Well, it means we're trying to link the same symbol name (in our case, a method) from two (or more) different source files. The fix was easy: rename one of the methods by updating the header file, the source file (.c or .cpp file) and lastly, updating your references to the symbol in your Go code, if it is directly referenced there."
Will it help ?
I was running into the same issue for hours and finally found the fix on a google groups channel
A package you import could be using cgo, you don't have to be using it directly
...
You can try CGO_ENABLED=0 go build and if it works then it is cgo related.
This was the charm that i was looking for! Hope this works for you too.

How can I remove a symbol in a library(.lib) under ccs

There are two library which contains one same symbol, this leads to a redefinition when linking the lib. How can I remove a specific symbol in a lib?
The developing environment is CCS3.3, the duplicated symbol is _sature which is defined in rst6740.lib.
Thanks in advance!
Good question !
In my opinion, you should rebuilt rst6740.lib.
You can find out the library code "rtssrc.zip" in folder that you setup the compiler.
Example : C:\ti\C6000_Code_Generation_Tools_7.3.7\lib.
That is code of library that will used to build the rts6740.lib,rts6400.lib...
Then you should remove the code of sature function and rebuilt the rst6740.lib.
How to rebuild this lib you can search in Google.
Now i don't remember clearly step by step to rebuild it.

shared linking against libB.so, libB.so.3, or libB.so.3.0?

Suppose I would like to create a library A that links against another (system) library B of which the following files are installed:
$ ll /usr/lib/libB*
libB.so -> libB.so.3
libB.so.3 -> libB.so.3.0
libB.so.3.0
When creating my own libA.so*, I suppose it'd be good practice to include any of libB.so* on the link line. In fact, the linker flag -Wl,--no-undefined even enforces this.
It doesn't seem to make a difference which of the above libB files are used for linking since eventually they all point to the same file libB.so.3.0, but I'm guessing there are best practices for this, too.
What's recommended and why?
What's recommended and why?
Only linking against libB.so is officially supported. Linking against libB.so.3 or libB.so.3.0 works more or less by accident; don't do it.
You can read about external library versioning here.

Why do I need to manually link the C runtime library when creating an EXE out of static libraries without any object files?

I'm pretty new to working with libraries and I'm in the process of trying to understand some specifics regarding static libraries and object files.
Summary
The behavior I'm noticing is that I can link several objects to make an executable with no problem, but if I take an intermediate step of combining those objects into static libraries, I cannot link those static libraries to make an executable without additionally specifying the needed C Run-time library in the link command.
Also, or the record, I'm doing the compiling/linking with Visual Studio 2010 from the command line. More details of the process I'm following are below.
First, let's say I have four source files in a project: main.c, util1.c, util2.c, and util3.c.
What works
I can compile these sources with the following command:cl -c main.c util1.c util2.c util3.cAs a result, I now have four object files: main.obj, util1.obj, util2.obj, and util3.obj. These object files each contain a DEFAULTLIB statement intended to inform the linker that it should additionally check the static C Run-time library libcmt.lib for any unresolved external dependencies in these object files when linking them.
I can create an executable named "app_objs.exe" by linking these objects with the following command:
link -out:app_objs.exe main.obj util1.obj util2.obj util3.obj
As mentioned in step 1, the linker used the runtime library due to the compiler's step of adding a default library statement to the objects.
Where I'm confused
Let's say I want to have an intermediate step of combining these objects into static libraries, and then linking those resulting LIB files to create my executable. First, I can create these libraries with the following commands:
link -lib -out:main.lib main.obj
link -lib -out:util.lib util1.obj util2.obj util3.obj
Now, my original thought was that I could simply link these libraries and have the same executable that I created in step 2 of "What works". I tried the following command and received linker error LNK1561, which states that an entry point needs to be specified:
link -out:app_libs.exe main.lib util.lib
From Microsoft's documentation, it is evident that linking libraries without any object files may require entry points to be specified, so I modified the command to set the subsystem as "console" to specify that the executable in intended to be a console application (which seems to imply certain entry points, thereby resolving that error):link -out:app_libs.exe -subsystem:console main.lib util.libUnfortunately, now I get a linker error stating that mainCRTStartup is an unresolved external symbol. I understand that this is defined in the C runtime library, so I can resolve this issue by manually specifying that I want to link against libcmt.lib, and this gives me a functioning executable:link -out:app_libs.exe -subsystem:console main.lib util.lib libcmt.lib
What I'm not understanding is why the default library info that the compiler placed in each object file couldn't be used to resolve the dependency on libcmt.lib. If I can link object files without explicitly stating I want libcmt.lib, and I created static libraries that are containers for the object files, why can't I link those static libraries without having to explicitly state that I want libcmt.lib? Is this just the way things are, or is there some way I could create the static libraries so that the linker will know to check for unresolved symbols in the runtime library?
Thanks for your help. If I have some fundamentally incorrect ideas here, I'd love suggestions on good references to learn all of this correctly.
Well the answer to your misunderstanding is that .lib files are often a product in themselves, and the compiler can't make those assumptions safely. That's what "external" is for.
If I produce binaries for someone's platform because its users are totally helpless, and they want/need static linkage, I have to give them foo.h and libfoo.lib without tying them to a specific runtime entry point. They may very well have defined their own entry point already for their final product, whether DLL or EXE.
You either want the runtime, or you want your own .obj that contains your entry point. Be warned that declaring and defining mainCRTStartup on your own may mean you're not executing important instructions for the target platform.

Statically linking multiple libraries with WinDDK

I am using the DDK to build a project. Several of the build targets generate small internal libraries -- for simplicity, let's call them LibA.lib, LibB.lib, and LibC.lib. But the code for LibA references code from LibB and LibC. To use LibA in a project, you also need to include LibB.lib, and LibC.lib to resolve all of the dependencies. What I want to do is link LibB and LibC into LibA such that a user only needs to include LibA.lib. How can I accomplish this?
The SOURCES file for LibA looks something like this:
TARGETNAME=LibA
TARGETTYPE=LIBRARY
TARGETPATH=..\lib\$(DDKBUILDENV)
INCLUDES = .; \
..\LibB; \
..\LibC; \
$(CRT_INC_PATH) \
$(SDK_INC_PATH)
SOURCES = LibA_main.cpp \
LibA_file2.cpp \
LibA_file3.cpp
I understand that you can manually link libraries with link.exe; e.g.,
link.exe /lib LibA.lib LibB.lib LibC.lib
But if possible, I would like some way to achieve this same effect as a part of the build process for LibA, because some targets at a later point of the build process rely on LibA.
Thanks!
I realize this is a late answer and it may not even be what you want in the end. However, ddkbuild.cmd has a pretty nifty mechanism to run actions before and after a build inside a particular directory.
We use this in one of our driver libraries which necessarily gets built as a number of static libraries and as a final step linked into one big static library much like you want. If you are able to use something like ddkbuild.cmd in your project, this would provide a solution and it's a solution that would work in automated builds, too.
NB: as far as I'm aware you cannot achieve what you want directly with build.exe. However, it's well possible that with some make (NMake) file acrobatics you could achieve a similar result. So the question is whether it's worth reinventing the wheel when there is one already.
I have encountered the same situation as you. Google a lot of and still have no solution. Fortunately, I found a way to resolve it finally. You can try it, add the below statement in your libA sources file.
LIBRARIAN_FLAGS = $(LIBRARIAN_FLAGS) libB.lib libC.lib
The lib utility can combine libraries. Using your example, the command would be:
lib /out:CombinedLib.lib LibA.lib LibB.lib LibC.lib

Resources