0

I have 2 files:

strong.cc

#include <stdio.h>
void foo(){
   printf("Strong is here\n");
}

weak.cc

#include <stdio.h>
void __attribute__((weak)) foo();
void foo(){
   printf("Weak is here\n");
}

and then my main.cc

#include <stdio.h>
extern void foo();
int main(int argc, char* argv[]) {
   foo();
   return 0;
}

First, I compiled the strong.c and weak.c to generate strong.so and weak.so respectively with

g++ strong.cc -o libstrong.so -shared -fPIC
g++ weak.cc -o libweak.so -shared -fPIC

Then, I compiled the main.c

g++ -c main.cc -o main.o

Lastly, I linked the main.o with the 2 other .so files

g++ main.o -L. -lweak -strong

What printed is:

Weak is here

Then when I reversed the order of linking to

g++ main.o -L. -lstrong -lweak

What printed is:

Strong is here

I searched for this, and I think it is a limitation (https://en.wikipedia.org/wiki/Weak_symbol) But I am constrained to have the linking in that order. So, is there any workaround or hack to overcome this limitation? Or is there a bug tracking page for this in GNU community that sets expectations on when will it be fixed?

I also tried the linking without the -l with g++ main.o libsim2.so libsim.so but I got the same results.

I tried a lot of options with g++ like --start-group <strong_lib> --end-group and --whole-archive and tried the version script with

{ 

global:

 *; 

local: 

*WeakSymbol*; 

};

But none of them worked and always the weak function overrides the strong function as it came first in the linking order.

  • 2
    Re “But I am constrained to have the linking in that order”: That is a weird constraint, and it is a problem because a solution is likely to involve changing linking in some way. So what other constraints about the link command do you have? I suspect the issue is that a weak symbol will be overridden if a non-weak definition is linked into the executable, but merely listing a library that has a non-weak definition does not link that module into the executable, because the linker does not take the module if it does not need it. Workarounds may involve changing the link command. – Eric Postpischil Aug 10 '23 at 12:29
  • It looks like you have authored `weak.c` and `strong.c`, but in your compile line, you are compiling `weak.cc` and `strong.cc`. These are not the same file! Are you sure you're building the files you think you are building? – abelenky Aug 10 '23 at 12:40
  • I am trying to have my strong function executed instead the weak one independently of the order of linking, which is I think the main idea of weak and strong functions, which is that the strong should override the weak if a strong definition was found during the linking process. This is the only constraint I have is that I am asking if I could get this without changing the order of linking. – Islam Ashraf Aug 10 '23 at 12:43
  • @abelenky edited thank you. there was a typo in the authored lines. – Islam Ashraf Aug 10 '23 at 12:45
  • https://stackoverflow.com/questions/13089166/how-to-make-gcc-link-strong-symbol-in-static-library-to-overwrite-weak-symbol has an example use of --whole-archive and references https://bottomupcs.com/ch09s05.html has some context that might be relevant to you. – Allan Wind Aug 10 '23 at 12:45
  • 2
    Re “This is the only constraint I have is that I am asking if I could get this without changing the order of linking”: Sure, link the strong version of the routine into the executable as an object module, not a library, but in the same order. – Eric Postpischil Aug 10 '23 at 12:48
  • This is exactly why C++ has the [One Definition Rule](https://en.cppreference.com/w/cpp/language/definition), to keep you out of these situations. Breaking it means undefined behavior. – Mark Ransom Aug 10 '23 at 12:57
  • @MarkRansom Yes that was my feeling too, just deleted my comment. If you want strong guarantees put them in a "strong" and "weak" namespace and select the function you really want. – Pepijn Kramer Aug 10 '23 at 13:00
  • Set LD_DYNAMIC_WEAK environment variable (to any value) and run the program. For explanation, see `man 8 ld.so`. – n. m. could be an AI Aug 10 '23 at 13:01
  • @OP you describe a HOW you want to solve something. But what is the actual problem you are having? A name clash between multiple 3rd party libraries? If so consider creating some staticially linkable wrappers with namespaces first that will only compile with the third party libraries (as a bonus you could even provide an abstract baseclass in the wrapper further decoupling you from the implementation details, and allowing 3rd party code to be mocked in unit tests) – Pepijn Kramer Aug 10 '23 at 13:02
  • 1
    @MarkRansom C and C++ are irrelevant here, tags notwithstanding. The same exact thing will happen if you write your code in assembly. The question is strictly about the GNU linker. – n. m. could be an AI Aug 10 '23 at 13:09
  • Thank you all for your contributions. Using the solution provided by @EricPostpischil worked successfully! Please write it as a solution to confirm. – Islam Ashraf Aug 10 '23 at 13:28
  • Also, the solution provided by @n.m.couldbeanAI worked! Please write it as a solution too. – Islam Ashraf Aug 10 '23 at 13:28
  • @n.m.couldbeanAI but why do you think C and C++ have the rule in the first place? Compilers and linkers may be independent, but they work together as a system. There is no universal linker specification so the C and C++ standards have to cover their limitations. – Mark Ransom Aug 10 '23 at 13:49
  • 1
    @MarkRansom: Re “This is exactly why C++ has the One Definition Rule, to keep you out of these situations”: No, that is not why it has the rule. It has the rule to keep those situations out of its jurisdiction. It is the programmer’s choice whether to get into the situation or not. The programmer may choose to use a linker’s weak-attribute features if they wish, and the meaning of the C++ standard’s rule is “If you do that, the standard has nothing to say about it [you can use the linker’s documentation].” It does not mean you cannot do or that you should not do it. – Eric Postpischil Aug 10 '23 at 13:52
  • 1
    @EricPostpischil perhaps I overstated the case a bit, there are other reasons for the ODR. There are plenty of ODR violations that are directly within the compiler's jurisdiction. You're right, the mere existence of `weak` means gcc intended you to violate the restriction for that particular case. – Mark Ransom Aug 10 '23 at 13:57

0 Answers0