Dynamic linking and derivative works
Armijn Hemel is an engineer in the Netherlands who was for several years actively involved with GPL enforcement at gpl-violations.org. In 2012, he retired from his core role there, and now concentrates on his own consultancy business that specializes in licensing compliance issues. In a talk at the 2013 Free Software Legal and Licensing Workshop, he focused on his research into dynamically linked ELF binaries. The aim of that talk was to present the results of some of his experimental investigations of the dynamically linked binaries that are shipped in (mainly) embedded systems and kickstart some discussion on the implications of dynamic linking for the creation of derivative works under the GPL license. In passing, he also spent some time discussing a tool that he uses to automate the kinds of binary analysis that he presented.
Investigating binaries
Armijn briefly explained ELF (Executable and Linking Format) and the advantages of dynamic linking. He then provided a simplified summary of the operation of dynamic linking for his lawyer audience, noting that, at build time, two pieces of information are recorded in a program binary: the symbols (functions, variables) that the program needs from each library, and the list of libraries that the program needs at run time (the "dependency list"). At run time, the undefined symbols are then resolved by the dynamic linker, which uses the dependency list to find the libraries that may have the needed symbols.
The key point is that the build-time and run-time environments may be different, Armijn said. This is important because, in his opinion, dynamic linking moves questions about derivative works and the application of the GPL license into run time, because it is only at run time that libraries are linked with a program. The dynamically linked libraries that are used at run time could indeed be different—and have different licenses—from the libraries that were specified during the static linking phase. This implies that (depending who you ask) declaring the wrong dependencies in a binary could trigger license compliance issues.
For his examples, Armijn showed some results of examining the firmware for one embedded device, the Trendnet TEW-636APB wireless access point. (The device and firmware are now a few years old, but serve to illustrate the points well.) The device came with source code, making it possible to verify his findings against the build scripts and code. The example program used for the analysis was the dynamically linked busybox program provided in that firmware, "because BusyBox is everyone's favorite whipping boy".
Armijn pointed out that if one scans all of the binaries in a filesystem to obtain the list of undefined and defined symbols in each binary, it is then (in principle) easy to perform manual symbol resolution. For any particular binary, one can do this by first using the command readelf -W --dyn-syms (coupled with suitable grep commands) to obtain (1) the list of undefined symbols from the binary and (2) the list of symbols defined by each of the declared dependencies of that binary. One can then match the undefined symbols from the binary with the defined symbols in the declared dependencies. As a result of that process, one can determine any leftover symbols that could not be resolved and any superfluous dependencies that were declared by the binary.
Armijn then showed an example of the results he found via this process when examining the busybox binary in the Trendnet TEW-636APB firmware. The declared dependencies of the busybox binary were as follows:
$ readelf -a busybox | grep NEEDED 0x00000001 (NEEDED) Shared library: [libutility.so] 0x00000001 (NEEDED) Shared library: [libnvram.so] 0x00000001 (NEEDED) Shared library: [libapcfg.so] 0x00000001 (NEEDED) Shared library: [libaplog.so] 0x00000001 (NEEDED) Shared library: [libcrypt.so.0] 0x00000001 (NEEDED) Shared library: [libgcc_s.so.1] 0x00000001 (NEEDED) Shared library: [libc.so.0]
Many developers believe that the existence of such a dynamic dependency list in a binary is sufficient to indicate that the binary is a derivative work, Armijn said. However, he doesn't believe that argument holds any weight.
The first four busybox dependencies are interesting, Armijn said. Having looked at thousands of firmware blobs, he did not recognize the filenames, suggesting that they are proprietary modules. Furthermore, those modules have no corresponding source code in the source code release, and since the GPL-licensed busybox links to those four shared objects, that would imply that there is a license violation.
"Or maybe not." Applying the process described above to the binaries showed that the libnvram.so and libaplog.so binaries are not used by busybox, although they are needed to satisfy the dynamic linker. On the other hand, busybox did use libutility.so and libapcfg.so, so that, in Armijn's opinion there was still a license violation.
![[Busybox dependencies]](https://static.lwn.net/images/conf/2013/fsllw/busybox_1-thumb.png)
Of course, libnvram.so and libaplog.so might still be used by other libraries that busybox depends upon. And, in fact, libnvram.so is used by libapcfg.so, so that that the combination of busybox and libnvram.so might also be a derived work of busybox. The diagram to the right shows the complete set of dependencies for the busybox binary. In the diagram, the black arrows represent dependencies between modules that are both declared and used to resolve symbols, while the dashed blue arrows represent dependencies that are declared but unused (i.e., unneeded for the purpose of symbol resolution).
Looking at the source code release showed the line in a makefile that created the superfluous dependencies for busybox:
LIBRARIES += -lutility -lnvram -lapcfg -laplog
The situation can be still more complicated, Armijn noted. Sometimes there are hidden dependencies—dependencies that are used to satisfy symbol resolution but not declared. In the busybox example, he discovered a number of such hidden dependencies. For example, the libapcfg.so binary depends on libutility.so and libaplog.so, but the binary does not declare those dependencies. (Shared libraries can have dependency lists in the same way that programs do.) The only reason that the program works is that the declared dependencies of the busybox binary ensure that the hidden dependencies of libapcfg.so (and some other binaries) are all satisfied.
Armijn pointed out further oddities that he has observed in the wild. He has seen examples of two libraries that offer the same symbols with both libraries being declared as dependencies—in one case, this was because the code of a smaller library was completely embedded inside a separate, larger library. He has also seen cases where libraries do not implement all the symbols that are required by the main program; the result is that the program may successfully run or it may crash, depending on whether a particular symbol needs to be (lazily) resolved at run time.
Binary Analysis Tool
Manually doing this sort of analysis using readelf is possible, but time consuming. For that reason, Armijn makes use of a suite of tools that greatly ease the task. That suite, which goes under the overall moniker Binary Analysis Tool (BAT), automates the inspection of filesystem images to ease the task of discovering binaries that are linked against GPLed binaries and issues such as superfluous dynamic dependencies.
The potential user base of BAT is varied, including groups performing GPL enforcement (as Armijn has done in the past), consultants who work with companies to help ensure that they comply with licensing obligations (as he does now), and companies who want to ensure that their products are license-compliant. The difficulty of the last task becomes clear when one realizes that those companies may have no easy way of checking the compliance of binaries delivered to them by third parties.
BAT consists of a set of Python scripts that are licensed under the Apache License v2. Since a common use case for BAT is to examine firmware blobs, the tool includes hooks that attempt to automatically decompress such blobs using a range of standard compression tools. A configuration file allows the user to specify further user-defined hooks for breaking apart blobs. The tool performs its inspection using various techniques, including string matching and symbol table matches (rather than disassembly, which is a legally gray area in some jurisdictions); the main algorithm is described in this article [PDF].
There are two primary tools in the BAT suite, bruteforce.py and batgui. bruteforce.py is a command-line tool that performs the binary analysis. bruteforce.py takes two inputs: a configuration file (a default configuration file is provided with the installation), and a filesystem image. It produces two outputs, a results file that is used by batgui and an XML file produced on standard output. The XML file can be used by some reporting tools. In addition, the script produces various output files in a directory specified in the configuration file.
![[batgui]](https://static.lwn.net/images/conf/2013/fsllw/BAT-busybox-thumb.png)
The results file can be viewed using the batgui script. The analysis information is displayed in two panes. On the left is a hierarchical tree structure representing the analyzed filesystem. On the right, information is displayed for the currently selected file from the left-hand pane. The right-hand pane has a number of tabs, one of which ("ELF analysis") shows the declared and unused dependencies when a binary is selected.
The tool is somewhat rough around the edges, but usable for its stated purpose; it is under active development, principally by Armijn, although outside contributions of various kinds are welcomed.
There are several near-term goals for improving the tool, including detecting unfulfilled dependencies, detecting duplicate dependencies (where a binary has dependencies on two different libraries that provide the same symbols), and supporting other languages (such as Java). The bruteforce.py script already generates dependency graphs of the form shown in the first part of this article. Those graphs are placed in the subdirectory specified in the configuration file; the graphs are not (yet) displayed by batgui, but supporting that feature is planned.
Derivative work: yes or no?
Having looked at a lot of firmware blobs by now, Armijn has discovered the superfluous-dependency issue (or hidden dependencies) in nearly all of them. So, his question to the audience was: does dynamic linking always make a derivative work? Is the act of dynamic linking—even if the dependency satisfies no symbols—enough, on its own, to constitute a derivative work? After all, he noted, if the dependency is not satisfied at run time, the program will not even start.
The Free Software Foundation GPLv2 FAQ is unequivocal that all forms of linking against a GPL-licensed binary create a derivative work, so that the terms of the GPL apply to all of the linked modules; many developers agree with this interpretation.
However, Armijn pointed out that there is considerable debate on whether dynamic linking creates a derivative work, especially among lawyers. For example, Lawrence Rosen even goes so far as to argue that no kind of linking (dynamic or static) creates a derivative work per se, as defined by the GPL. "And to be honest, I think he has a fair point."
A wide range of opinions came back from the Workshop audience. Claus-Peter Wiedemann was of the opinion that static or dynamic linking is just one indicator for a derived work. Other questions need to be answered as well. Is there a functional dependency between the modules? What data is exchanged between the two modules? Can the library be exchanged with another one? Is the interface standard or proprietary? In response, Armijn asked the following rhetorical question: "So how does one get this message out to developers, many of whom consider that if they run ldd on a binary, then the revealed dependencies are sufficient to prove that this is a derivative work?"
Daniel German suggested that Armijn was looking too hard for a problem. The superfluous dependency problem seems to be just an unintentional error (rather than the intentional creation of a derivative work); people could just fix it, and then everyone is happy.
James Bottomley pointed out what he considered a key difference between dynamic and static linking, which hinges on who creates the derivative work. With static linking it is the distributor who creates the derivative work. With dynamic linking, it is the end user who (at run time) creates the derivative work. Thus, in his opinion, other legal arguments would need to be brought forward to claim that the distributor is distributing a derivative work.
In response to James, another audience member countered that if one distributes a complete package that includes the shared libraries, it's hard to argue that the result is not the distribution of a derivative work, even if the linking is done dynamically. On the other hand, if one supplies just a piece of code that is then compiled and built by the user, then it may be more legally viable to claim that a derivative work has not been created. Till Jaeger made a similar point, noting that the decision about whether or not a derivative work has been created can't be based on technical factors alone, but rather on factors such as the relationship between pieces of code. "Suppose I add an interface to a GPL-licensed program to implement new functionality in a shared library; then of course it is a derivative work [regardless of the type of linking]."
Readers interested in further legal perspectives about dynamic linking and derivative works can also consult Chapter 6 [PDF] of Lawrence Rosen's book, Open Source Licensing, as well as this viewpoint [PDF] from another lawyer, Andrew Katz. A discussion of the GPL and derivative works can be found in this article from the University of Washington. As noted in the IFOSSLR article Software Interactions and the GNU General Public License and the associated Working Paper on the legal implications of linking [ODT] by the FSF Europe's Software Interactions working group, even if it is argued that dynamic linking does not create a derivative work, other arguments can come into play, such as interdependency and "collectivity"—co-distribution of a program and the GPLed library against which it dynamically links.
Concluding remarks
Armijn's presentation was thought provoking, especially insofar as it
raised the subtleties around dynamic linking and derivative works. Although
the Free Software Foundation is adamant that linking of any kind creates a
derivative work, in the end it is the courts that will decide that
point. It is interesting that as one gets closer to the legal system (i.e.,
when one talks to lawyers), opinion about whether (dynamic) linking creates
a derivative work is rather less clear cut. That is not to say that
dynamically linked binaries might one day be legally interpreted as not
being derivative works; rather, the decision about what constitutes a
derivative work is likely to be argued and decided on much more than single
technical factors such as how two pieces of code are linked together.
Index entries for this article | |
---|---|
Conference | Free Software Legal & Licensing Workshop/2013 |
Posted Apr 25, 2013 2:38 UTC (Thu)
by tstover (guest, #56283)
[Link] (9 responses)
A better question is why would someone try to figure out ways to steal from a person producing GPL libraries?
Also, by definition, lawyers will always be debating all things related to the law. Saying you can find some lawyers who don't think dynamic linking is derivative is not in and of itself a reason for anything. At least be creative enough to debate what it means to agree to the license terms.
Posted Apr 25, 2013 4:36 UTC (Thu)
by Cyberax (✭ supporter ✭, #52523)
[Link] (4 responses)
Posted Apr 25, 2013 13:30 UTC (Thu)
by tstover (guest, #56283)
[Link] (3 responses)
Posted Apr 25, 2013 13:43 UTC (Thu)
by kpfleming (subscriber, #23250)
[Link]
If however, the resulting work just uses the knowledge gained from the header files (symbol/function names, argument lists, return values, etc.), then that's the API described by the header files, and the Oracle v. Google judgement could mean that the resulting work is *not* a derivative of the header files and their copyrights/licenses don't affect it.
Posted Apr 25, 2013 15:17 UTC (Thu)
by Cyberax (✭ supporter ✭, #52523)
[Link] (1 responses)
You probably can just strip all comments and redistribute the result (which is essentially what MinGW does, anyway).
Posted Apr 25, 2013 19:40 UTC (Thu)
by dashesy (guest, #74652)
[Link]
Posted Apr 26, 2013 8:38 UTC (Fri)
by armijn (subscriber, #3653)
[Link] (1 responses)
Posted Jun 4, 2013 21:03 UTC (Tue)
by oever (guest, #987)
[Link]
Have you ever looked at matching patterns in the assembly? The source code compiles to assembly (exactly how depends on the compiler type, version, options and phase of the moon) but certain patterns associated with snippets of code might recur.
Posted Apr 28, 2013 3:01 UTC (Sun)
by giraffedata (guest, #1954)
[Link] (1 responses)
Actually, what it means to agree to the license terms is not interesting, since agreeing to those terms has no legal significance. There's no contract involved. The copier meets the conditions and thereby has a license to copy, prepare a derivative work, etc. Or he doesn't and he doesn't. There is no subsequent obligation such as when someone agrees to pay interest on a loan and then he has to do it.
Now debating what it means to comply with the conditions of the license - that would be worth debating.
Posted Apr 30, 2013 17:59 UTC (Tue)
by ultach (guest, #90476)
[Link]
Not strictly true in the EU---as for the US there may exist a contract not to revoke the license, whether unilaterally or in the event of license terms not being adhered to.
So contract/license? elements of both and not possible to say which without looking at the relationship which the license is supposed to embody.
Posted Apr 25, 2013 6:44 UTC (Thu)
by halla (subscriber, #14185)
[Link] (3 responses)
So busybox links against a set of proprietary libraries, but that should be fine, right? Just like any GPL application on Windows links against a set of proprietary libraries. That the application is GPL, doesn't mean the platform it runs on needs to be GPL's?
Posted Apr 25, 2013 14:48 UTC (Thu)
by tseaver (guest, #1544)
[Link] (2 responses)
Posted Apr 25, 2013 16:02 UTC (Thu)
by halla (subscriber, #14185)
[Link] (1 responses)
I'm still puzzled :-) Posted Apr 25, 2013 20:16 UTC (Thu)
by aleXXX (subscriber, #2742)
[Link] (1 responses)
(Ok, in practice this does not happen often, that you have the same library in different implementations with different licences but binary compatible.)
Alex
Posted Apr 25, 2013 23:57 UTC (Thu)
by JoeBuck (subscriber, #2330)
[Link]
People mistakenly claimed at the time that the FSF was claiming an interface copyright on GMP. They weren't; they were saying that if a program is useless without a GPL component, and the developer is using that component in house and ships build scripts or instructions that build a derivative work on the end user's machine, they are conveying a derivative work and the technical means don't matter, just the end result. But they can't stop end users from swapping out an inferior component and replacing it with a superior one, even if the result can't be distributed.
So, for the shared library question, I would say that the issue is whether the only usable providers of the interface are GPL libraries and whether the build instructions or script is clearly sucking in that GPL code somehow.
Posted Apr 26, 2013 8:10 UTC (Fri)
by Uraeus (guest, #33755)
[Link] (1 responses)
Posted Apr 28, 2013 19:11 UTC (Sun)
by SLi (subscriber, #53131)
[Link]
No; it only matters to the extent that the copyright holder of one part can legally prevent the other part from doing something.
And that's precisely the derived work question. Some people always complain that GPL doesn't define "derived work". Well, there's a reason for it: It cannot. What is and what is not a derived work is not a question of license text, but a question of copyright law.
Now, if the way someone uses GPL code does not constitute making a derived work, the intent of the copyright holder matters little. Even if the copyright holder unequivocally announces that he considers, for example, dynamic linking to constitute making a derived work, if it's not, he simply has no authority to prevent the other party from doing whatever it is they're doing.
In legal terms, making a derived work is one of the exclusive rights of the copyright holder. It is one of the things that the owner can legally prevent others from doing. Conversely, the copyright owner can only prevent others from exercising one of the exclusive rights. Linking is not one of the exclusive rights. Making derivative works is. Therefore, the question is fundamentally about derived works, not about linking, no matter what the copyright holder expresses his intent to be.
Posted Apr 26, 2013 9:09 UTC (Fri)
by aleXXX (subscriber, #2742)
[Link] (10 responses)
Let's say I have some code, written in javascript and translate it to ruby.
Posted Apr 26, 2013 9:50 UTC (Fri)
by mpr22 (subscriber, #60784)
[Link] (9 responses)
My understanding (I am not a lawyer and this is not legal advice) is that translating the JS code into Ruby code would be translation, which is derivation, which is an act restricted by copyright law. Reimplementing the external interface of the JS program from scratch in Ruby without looking at the internal implementation details of the JS program, on the other hand, would not in general be derivation covered by copyright.
Posted Apr 28, 2013 2:56 UTC (Sun)
by giraffedata (guest, #1954)
[Link] (8 responses)
I think that's exactly right. I'm not a copyright lawyer either, but I've studied copyright plenty. This is a direct analogy to age-old settled copyright law that says translating a novel from English into Russian is preparing a derivative work, and therefore requires the permission of the copyright holder of the English novel. It's also why distributing object code you compiled yourself from source requires the permission of the person who wrote the source code.
What's especially interesting about the copyright owner's right to restrict preparing derivative works is that you don't even have to distribute, perform, or make a copy. You need permission just to prepare it. I know of a case where a video editor made a business of editing VHS copies of the movie Titanic, removing two pieces of tape to change it from PG-13 to PG. This was almost the opposite of copying - the customer got back less material than he started with. The copyright owner said the editor needed its permission for that, and it was a plausible enough claim that the editor stopped doing it.
Posted Apr 28, 2013 4:23 UTC (Sun)
by Cyberax (✭ supporter ✭, #52523)
[Link] (7 responses)
For example, you can get a piece of Titanic, translate it into Klingon and use it in a classroom (fair use).
You can't automatically _redistribute_ the result, though.
Posted Apr 28, 2013 7:13 UTC (Sun)
by giraffedata (guest, #1954)
[Link] (6 responses)
If your point is that there are exceptions to the restriction in US law on preparing derivative works, I agree. So my blanket statement that you need permission was incorrect (oversimplified, actually).
It's worth noting that the exceptions are not unique to derivative works. They apply to public performances and plain old copies as well.
Posted Apr 28, 2013 8:18 UTC (Sun)
by Cyberax (✭ supporter ✭, #52523)
[Link] (5 responses)
Posted Apr 28, 2013 18:18 UTC (Sun)
by giraffedata (guest, #1954)
[Link] (2 responses)
Perhaps you would like to provide a shred of an argument for this? Otherwise, no one reading this thread, including me, is going to believe you, because the thread contains multiple shreds of argument that the opposite is true.
I wonder if you're confusing copyright in general with GPL, because GPL gives everyone permission to create derivative works with no strings attached as long as they don't distribute the result.
In fact, there's another shred of evidence for the proposition that you need permission to create a derivative work. GPL is full of clauses explicitly giving people permission to modify the program. That strongly suggests the copyright lawyers who wrote it believed permission was required.
Posted Apr 28, 2013 19:23 UTC (Sun)
by sfeam (subscriber, #2841)
[Link] (1 responses)
Posted Apr 28, 2013 21:55 UTC (Sun)
by giraffedata (guest, #1954)
[Link]
Thanks. That helps a little, but since we've already established that there are exceptions, it doesn't go very far toward proving that in general one doesn't need permission to create (and not distribute) a derivative work. The refrigerator photo could be an application of the fair use exception in copyright.
I also think it's strange that taking a photo of a painting is creating a derivative work as opposed to making a straight-up copy (like photocopying a book), but I'll take your word for it. I guess there is some art involved in taking the photo and that may make the difference.
You piqued my interest in the application of copyright to photography enough to read the web page you cited, and happened to come across this, giving more weight to the proposition that you do generally need permission to create a derivative work:
Posted May 2, 2013 13:02 UTC (Thu)
by Wol (subscriber, #4433)
[Link] (1 responses)
Creating a derivative work without permission is verboten. End of! (Obviously, we have the Performing Rights Society and other means of enforced licencing - I'm not sure whether that's a good thing or not.)
The fact that prosecution is unlikely doesn't affect the fact that it is illegal. There's also the civil/criminal dichotomy. Creating a derivative work is a civil tort, for which the copyright holder can sue for damages. Given our "loser pays" rules, a lawsuit is likely to end in tears for said copyright holder. However, creating a derivative work for profit is a criminal offence - not a good idea.
(Loser pays - if I make an illegal copy and, when sued, offer to settle for say, £100, I'm gambling that a jury will set damages lower. If I gamble right, the copyright holder will be liable for my defence costs...)
Cheers,
Posted Jun 4, 2013 22:19 UTC (Tue)
by hummassa (subscriber, #307)
[Link]
Posted May 9, 2013 11:01 UTC (Thu)
by nix (subscriber, #2304)
[Link]
Of course, this would all fail completely if you use LD_BIND_NOW. And, hey, it could get even worse: the interplay of LD_PRELOAD, /etc/ld.so.preload, symbol interposition, -Bsymbolic, DT_GROUP, DT_AUXILIARY, DT_FILTER and dlmopen() can make it really rather difficult to figure out just which of a bunch of warring symbols is used to satisfy a given unresolved symbol. Of course, most of these were added by Solaris and Linux basically doesn't use them. Thank goodness.
ELF seems to have grown a little overcomplicated...
what is the goal exactly?
what is the goal exactly?
what is the goal exactly?
what is the goal exactly?
what is the goal exactly?
From what I have read MinGW goes to a great length to have 100% clean room reveres engineering (you should not even look at those header files to contribute). There is also MinGW-w64 which is a different project with less rigorous restrictions. what is the goal exactly?
BTW, The header files could contain much more than just comments and function signatures, boost templates is just one example.
what is the goal exactly?
what is the goal exactly?
what is the goal exactly?
At least be creative enough to debate what it means to agree to the license terms.
what is the goal exactly?
Dynamic linking and derivative works
Dynamic linking and derivative works
Dynamic linking and derivative works
Dynamic linking and derivative works
If I can "simply" replace the let's say GPL implementation of the library with my own, let's say BSD-licensed implementation, isn't it kind of strange to say that my application would be a derived work of the GPL'd implementation of that library ?
Exactly this case came up in a controversy over use of the GPL2-licensed GMP library by code (RSAREF) with an incompatible license. Someone then produced a BSD-licensed library called FGMP, that provided the same interface but was not as good. RMS agreed that the FSF no longer had an objection to RSAREF, even though in practice no one actually used FGMP. Its existence alone meant that the FSF could no longer argue that RSAREF was effectively a derivative work of GMP via the user-does-the-link trick (originally the program would not work without GMP).
Dynamic linking and derivative works
Dynamic linking and derivative works
Dynamic linking and derivative works
What is "Copying"...
Is this copying ?
What is "Copying"...
What is "Copying"...
What is "Copying"...
Nope. You can prepare derivative copies without owner's permission (in USA and Russia, can't speak for other countries).
What is "Copying"...
Nope. You can prepare derivative copies without owner's permission (in USA
For example, you can get a piece of Titanic, translate it into Klingon and use it in a classroom (fair use).
What is "Copying"...
What is "Copying"...
No. It's a fundamental stuff - you are NOT limited in creation of derivative works.
Here is a shred of an argument. Taking a photograph of a copyrighted work is considered to constitute creation of a derivative work. Nevertheless in most cases it is permissible to do so if the photograph is not distributed. Quoting from WIPO:
"In most countries, you are allowed to take photos without authorization, if you use them purely for private purposes. For example, taking a photo of a painting to post on your home refrigerator will generally not constitute copyright infringement."
What is "Copying"...
What is "Copying"...
One of the exclusive rights of a copyright owner is the right to create derivative works from his work – that is, new works based upon or adapted from the original work. You should take care when you digitally manipulate other’s images, as this is likely to be a copyright infringement unless you have obtained the copyright owner’s prior permission.
What is "Copying"...
Wol
What is "Copying"...
Dynamic linking and derivative works
He has also seen cases where libraries do not implement all the symbols that are required by the main program; the result is that the program may successfully run or it may crash, depending on whether a particular symbol needs to be (lazily) resolved at run time.
The craziest case I've ever seen involved a library that referenced a bunch of symbols satisfied by nothing in the ELF symbol resolution chain at all -- but the library worked, because before those symbols were (lazily) resolved, the library dlopen()ed a shared library that provided those symbols. If you're twisted enough, you don't need to use dlsym() just because you're using dlopen()...