Instrumenting source, unresolved external function

Goal: Instrument program with timers within each function.
Problem: I am having trouble running my .ll (and .bc) files in the JIT.

Sample Error Message: LLVM ERROR: Program used external function ‘__ZTextureLinearDimensionEv’ which could not be resolved

The error message above is a sample that I have gotten, and I want to highlight my methodology to see if there are any holes in this process. Any help is certainly appreciated! (And perhaps this will be a useful guide for others later on)

(1) I have a large codebase, it contains hundreds of .cpp files.
(2) I want to instrument every .cpp file and add simple timers for profiling purposes.
(3) So I use cmake to build my project.
(4) So far so good, I can compile my project without errors.
(5) Now, for the source files I have, I compile again, but this time emit bitcode(Note: I do a .bc and .ll version).

The original compile command:
clang++ -Isome_directory -c source1.cpp -o source1.o

Becomes this:
clang++ -S -emit-LLVM -Isome_directory -c source1.cpp -o source1.cpp.ll

(6) Now I have a collection of hundreds of .ll files. I use llvm-link to make one large .ll file (combined.ll). There are no duplicated symbols, and only 1 main function found–great!
(7) Next I run my function pass using the opt tool on combined.ll, and then emit a new .ll file (lets call it optimized.ll) that has instrumented every function.
(8) No errors at this point and I have an instrumented version of my source code.
(9) Now I run “lli optimized.ll”, and eventually get the above sample error message.
(10) This seems somewhat reasonable. I have realized that the functions I have not instrumented may be in shared libraries and thus cannot be instrumented. However, there must be a way to link to dynamic/shared libraries them using LLI that I am missing.

So a few specific questions:
0.) When using lli, is it absolutely necessary that I have all of the source code (including the libraries)?
a.) I am wondering, because I am not sure if LLVM’s JIT is supposed to be used as I am doing so.
1.) What command line option am I missing to load libraries with lli? (Is there a -Linsert_library flag I need to add?)
a.) I am assuming if I can do this, this tells lli that there is an external function named __ZTextureLinearDimensionEv that it can use. (There is the -load argument, is this what I am missing)
2.) Do I ever have any hope of instrumenting the shared libraries with my function pass?
a.) I was thinking if I can generate a .ll after link-time, when I have all of the code then I might be in luck and can even profile the shared libraries. I guess the real question here is what can I do with link-time optimization in its current state?
3.) Do I ever have any hope of instrumenting the static libraries with my function pass?
a.) Same question as above, but I am hoping this option may work (again, perhaps with the -load argument).
4.) Eventually, once I have optimized.ll working, I want to use llc to generate an object file then compile to an instrumented executable to maximize performance (as opposed to only running my application with lli). Are any problems foreseen at this stage if I indeed can run my program with lli

Apologies if this is a long question, but I think this will clear up questions I have about statically instrumenting a program and then profiling it.


Tool sources: