1

On stack overflow there are numerous threads of people confused with linking weak symbols to the static library. In short, when using only object files (and no libraries), weak will always be overwritten as a symbol by a strong counterpart. But when using static libraries things get confusing. I will not explain the differences here, but there are threads on stack overflow that explain them. My question here is why did they make it that way? Currently that makes no sense to me.

EDIT

Links to the related stack overflow threads:

Explanation of confusing:

The purpose of weak is (in my mind) so the user can overwrite a function with their own when it is needed (or for the language internal usage, e.g., for inline), but when a library creator overwrites a function inside of the same (or underlying) archive it is not overwritten, the linker simply chooses the first definition it sees. Which is not consistent with the "flat" (libraryless) structure.

Dino Saric
  • 107
  • 7

1 Answers1

3

The purpose of weak is (in my mind) so the user can overwrite a function with their own when it is needed (or for the language internal usage, e.g., for inline),

Yes and no. I would narrow that a bit and change the focus: the purpose of weak symbols is so that a library can provide default implementations of certain functions that others of the library's functions use, yet also allow programs using that library to substitute their own implementations.

Moreover, although that does not preclude use by static libraries, it is intended primarily for dynamic libraries, because you don't need weak symbols for that purpose when you are linking static libraries. Shared libraries, on the other hand, need to be built differently and have support from the dynamic linker to allow such substitutions.

but when a library creator overwrites a function inside of the same (or underlying) archive it is not overwritten, the linker simply chooses the first definition it sees.

And? The creator of a static library has control of its contents, including their order. If they mean to provide a particular strong definition of a given symbol, then it is at minimum wasteful to put any other external definitions of that symbol into the same library.

Yes, a static linker could nevertheless cover for library authors on that score, but this scenario is not the one that weak symbols were designed to support, so why should linker maintainers be expected to expend work to implement that, and commit to maintaining it indefinitely?

Which is not consistent with the "flat" (libraryless) structure.

That depends on how you perform the link in the "flat" case. Also, linking a collection of (only) object files into a complete program is still not the scenario that weak symbols were designed to support.

why did they make it that way?

You would have to ask the designers if you want an authoritative answer, but my take is that the authors and maintainers of the GCC toolchain decided that the static link behavior you are asking about was a reasonable compromise between the complexity of the tools and the ideal semantics of weak symbols. They were likely influenced in this area by the SUN tools, which may effectively have been where the decision actually was made.

The chosen details serve the intended purpose for weak symbols just fine, and I am fairly confident that one library containing both weak and strong definitions of the same symbol was not among the use cases that guided the the tools' design. That the behavior of linking object files directly differs from that of linking them from a static library could be considered inconsistent, but that's a question of your mental model of the process. In any case, I am inclined to think that the question asked at the time was "what is the user most likely to mean?", and by no means is it clear that the answer to that would be the same for linking multiple object files (presumably all provided by the program / library author) as for linking a static library (frequently provided by a third-party).

John Bollinger
  • 160,171
  • 8
  • 81
  • 157
  • Thank you for the great answer. I have a follow-up question. I am working on embedded (bare-metal) devices, and here dynamic libraries are a no go.I understand now from your post that the weak keyword was designed for that. In embedded, weak keyword is used often as you mentioned, in static libraries so the application can overwrite the weak function. Okay, I see your point about `weak` and `strong` in the same library and that that is understandable that they did not implement that. – Dino Saric Jan 13 '22 at 07:38
  • But, do you think that they must cover this use-case? `app` -> `lib1` -> `lib_in_lib1` (-> = contains library). Let's `lib_in_lib1` have a `weak`symbol `x`. Let `lib1` have a strong symbol `x`. In this use-case, (btw., I am currently running into this problem) the current implementation of the linker will use the `weak` symbol `x` from `lib_in_lib1`. But, if the strong symbol `x` is in the `app` than weak works "as expected". What are your thoughts about that? Do you think this is an okay behavior? Do you see a big hickup here on why this was implemented like this? – Dino Saric Jan 13 '22 at 07:48
  • 1
    @DinoSaric, your `->` is only in your mind. Applications and static libraries do not contain other static libraries in any sense that retains the identity or coherency of the contained library, so `lib1` as you are describing it is simply a static library with both strong and weak definitions of `x`. Which is, again, a choice made by the developers of `lib1`, and not a recommended one. Also, note well that the static link behavior you describe for the case in which a definition of `x` appears in `app` does not depend on definition(s) of `x` in `lib1` being weak. – John Bollinger Jan 13 '22 at 14:16
  • 1
    Thus, @DinoSaric, I do not consider the observed link behavior described in your followup to be buggy or even unexpected. Weak symbols just don't have the semantics you are looking for. They are largely a workaround for the fact that the approaches traditionally applied with static linking, which revolve around control of library contents and of link order, are not sufficient for shared libraries. It is the traditional approaches that you should be looking at for your purposes. – John Bollinger Jan 13 '22 at 14:27
  • Cool, thank you for the insightful answer explaining my shortcomings. – Dino Saric Jan 14 '22 at 15:35