Why does weak attribute in gcc work differently in static library than for object files?

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:

  • 1
  • 2
  • 3
  • 4
  • 5

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.


Solution 1:

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).