<div dir="ltr"><div dir="ltr">Hi Stefan,<div><br></div><blockquote class="gmail_quote" style="margin:0px 0px 0px 0.8ex;border-left-width:1px;border-left-style:solid;border-left-color:rgb(204,204,204);padding-left:1ex">"a lot of non-trivial surface area" is a very polite description of the C++ symbols disaster :)</blockquote><div><br></div><div>Indeed. I think tooling may make this tractable: E.g. if debug info is available then perhaps we can make a tool to synthesize ASTs for classes that the user wants to mock. I haven't had a chance to think through the ideas in detail yet though.</div><div><br></div><div>-- Lang.</div></div></div><br><div class="gmail_quote"><div dir="ltr" class="gmail_attr">On Sun, Aug 16, 2020 at 1:32 PM Stefan Gränitz <<a href="mailto:stefan.graenitz@gmail.com">stefan.graenitz@gmail.com</a>> wrote:<br></div><blockquote class="gmail_quote" style="margin:0px 0px 0px 0.8ex;border-left-width:1px;border-left-style:solid;border-left-color:rgb(204,204,204);padding-left:1ex">
  
    
  
  <div>
    Hi Lang<br>
    <br>
    Thanks for explaining the new mocking and testing feature in the
    llvm-jitlink tool in such great detail! Indeed, it sounds like an
    interesting by-product of your jitlink efforts.<br>
    <br>
    "a lot of non-trivial surface area" is a very polite description of
    the C++ symbols disaster :)<br>
    <br>
    Best<br>
    Stefan<br>
    <br>
    <div>On 10/08/2020 08:26, Lang Hames wrote:<br>
    </div>
    <blockquote type="cite">
      
      <div dir="ltr">Hi All,
        <div><br>
        </div>
        <div>There was no update last week -- I'm still trying to get
          back into a regular schedule.</div>
        <div><br>
        </div>
        <div>Open-source changes since the last update were:</div>
        <div><br>
        </div>
        <div>(1) Some bug fixes for JITLink MachO / arm64 support
          (PAGE21/PAGEOFF12 now handle addends correctly).</div>
        <div>(2) llvm-jitlink now supports loading archives as well as
          relocatable objects.</div>
        <div>(3) llvm-jitlink now supports basic object-file level
          mocking and testing.</div>
        <div><br>
        </div>
        <div>That last one is unusual so I want to expand on it. The
          llvm-jitlink tool acquired a couple of new options to support
          this feature: "--phony-externals" which resolves all otherwise
          unresolved symbols to null instead of erroring, and "-harness"
          which allows a set of objects to be designated as a test
          harness, with the regular object files implicitly treated as
          objects to be tested. If the -harness option is passed
          llvm-jitlink installs a JITLink plugin to make some
          modifications to the usual linker rules:</div>
        <div><br>
        </div>
        <div>-- All symbols referenced by the harness object(s) are
          promoted to default visibility so that the harness can
          directly access static symbols inside the test object(s)</div>
        <div>-- All symbols defined by the harness object(s) override
          (rather than clashing with) symbols defined in the test
          object(s).</div>
        <div><br>
        </div>
        <div>With these modifications in place we can selectively test
          functions in an object file by mocking their callees. For
          example, suppose we have an object file, test_code.o, compiled
          from the following C source (which we do not have access to):</div>
        <div><br>
        </div>
        <div><font face="monospace">void irrelevant_function() {
            irrelevant_external(); }</font></div>
        <div><font face="monospace"><br>
          </font></div>
        <div><font face="monospace">int function_to_mock(int X) {</font></div>
        <div><font face="monospace">  return /* some function of X */;</font></div>
        <div><font face="monospace">}<br>
          </font></div>
        <div><font face="monospace"><br>
          </font></div>
        <div><font face="monospace">static void function_to_test() {</font></div>
        <div><font face="monospace">  ...</font></div>
        <div><font face="monospace">  int Y = function_to_mock();</font></div>
        <div><font face="monospace">  printf("Y is %i\n", Y);</font></div>
        <div><font face="monospace">}</font></div>
        <div><br>
        </div>
        <div>We would like to know how function_to_test behaves when
          we change the behavior of function_to_mock. We can do this by
          writing a test harness:</div>
        <div><br>
        </div>
        <div><font face="monospace">void function_to_test();</font></div>
        <div><font face="monospace"><br>
          </font></div>
        <div><font face="monospace">int function_to_mock(int X) {</font></div>
        <div><font face="monospace">  printf("used mock utility
            function\n");</font></div>
        <div><font face="monospace">  return 42;</font></div>
        <div><font face="monospace">}</font></div>
        <div><font face="monospace"><br>
          </font></div>
        <div><font face="monospace">int main(int argc, char *argv[]) {</font></div>
        <div><font face="monospace">  function_to_test():</font></div>
        <div><font face="monospace">  return 0; </font></div>
        <div><font face="monospace">}</font></div>
        <div><br>
        </div>
        <div>This harness code could not be linked against test_code.o
          under normal circumstances: function_to_test is static and
          will fail to resolve from the harness code, function_to_mock
          is a duplicate definition, and irrelevant_external is
          undefined. Our new llvm-jitlink options take care of these
          issues however, and running the test looks like:</div>
        <div><br>
        </div>
        <div><span style="font-family:monospace">% clang -c -o
            test_code_harness.o test_code_harness.c</span><br>
        </div>
        <div><font face="monospace">% llvm-jitlink -phony-externals
            test_code.o -harness test_code_harness.o</font></div>
        <div><font face="monospace">used mock utility function</font></div>
        <div><font face="monospace">Y is 42</font></div>
        <div><br>
        </div>
        <div>This utility may be of interest to people who want to
          perform some very late testing on build products to verify
          that compiled code behaves as expected. On basic C test cases
          it works reasonably well. C++ test cases are another matter:
          Any code involving classes tends to have a lot of non-trivial
          surface area (e.g. vtables) that would require great care to
          mock. Perhaps we need a new tool to tackle that problem.</div>
        <div><br>
        </div>
        <div>In the meantime, if nothing else this provides a neat
          example of how JITLink plugins can be used to modify the
          default linker behavior.</div>
        <div><br>
        </div>
        <div>Regards,</div>
        <div>Lang. </div>
      </div>
    </blockquote>
    <pre cols="72">-- 
<a href="https://flowcrypt.com/pub/stefan.graenitz@gmail.com" target="_blank">https://flowcrypt.com/pub/stefan.graenitz@gmail.com</a></pre>
  </div>

</blockquote></div>