<div dir="ltr"><div>I think I would expect this to work in general for ELF targets, as long as both the global variable and the function are either not comdat members or members of the same comdat.</div><div><br></div><div>If I compile your example to .ll I get:</div><div><br></div><div>@__sancov_gen_.5 = private constant [3 x i8*] [i8* bitcast (%"class.std::basic_ostream"* (%"class.std::basic_ostream"*, i8*)* @_ZStlsISt11char_traitsIcEERSt13basic_ostreamIcT_ES5_PKc to i8*), i8* blockaddress(@_ZStlsISt11char_traitsIcEERSt13basic_ostreamIcT_ES5_PKc, %if.then), i8* blockaddress(@_ZStlsISt11char_traitsIcEERSt13basic_ostreamIcT_ES5_PKc, %if.else)], section "__sancov_pcs", align 8</div><div><br></div><div>and later:</div><div><br></div><div><div>define available_externally dereferenceable(272) %"class.std::basic_ostream"* @_ZStlsISt11char_traitsIcEERSt13basic_ostreamIcT_ES5_PKc(%"class.std::basic_ostream"* dereferenceable(272) %__out, i8* %__s) local_unnamed_addr #3 {</div></div><div>  ...</div><div>}</div><div><br></div><div>The initializer is referencing a function with available_externally linkage, which I wouldn't expect to work because the object file will not contain a definition of the function. If I create a .s file from your example and remove the definition of __sancov_gen_.5 I can produce an object file using llvm-mc.</div><div><br></div><div>So I would probably try changing the instrumentation pass to skip available_externally functions.</div><div><br></div><div>Peter</div></div><div class="gmail_extra"><br><div class="gmail_quote">On Fri, Jul 28, 2017 at 6:03 PM, Kostya Serebryany <span dir="ltr"><<a href="mailto:kcc@google.com" target="_blank">kcc@google.com</a>></span> wrote:<br><blockquote class="gmail_quote" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex"><div dir="ltr"><div>Hi, </div><div><br></div><div>The LangRef warns that "blockaddress(@function, %block)" has a limited and target-dependent applicability:  <a href="https://llvm.org/docs/LangRef.html#addresses-of-basic-blocks" target="_blank">https://llvm.org/docs/<wbr>LangRef.html#addresses-of-<wbr>basic-blocks</a></div><div><br></div><div>But I wanted very much to save addresses of blocks in a global variable and so I did: </div><div><br></div><div>% cat cond.c </div><div>void foo(long *a) { if (a) *a = 0; }</div><div><br></div><div><div>% clang -O1  -c  cond.c   -fsanitize-coverage=inline-<wbr>8bit-counters,pc-table -S -o - -emit-llvm </div></div><div><br></div><div><div>@__sancov_gen_.1 = private constant [3 x i8*] [i8* bitcast (void (i64*)* @foo to i8*), i8* blockaddress(@foo, %entry.if.end_crit_edge), i8* blockaddress(@foo, %if.then)], section "__sancov_pcs", align 8</div></div><div><br></div><div>Is this expected to work? </div><div>If not, is it reasonable to try to make it work? </div><div><br></div><div>This works almost as I want it to, but not quite entirely:</div><div>% cat cout.cpp</div><div><div>#include <iostream></div><div>void Foo() { std::cout << ""; }</div></div><div><br></div><div>% clang++   -fsanitize-coverage=inline-<wbr>8bit-counters,pc-table cout.cpp -O1</div><div><div>fatal error: error in backend: Undefined temporary symbol</div></div><div><br></div><div>(the error message was added in <a href="http://llvm.org/viewvc/llvm-project?view=revision&revision=253328" target="_blank">http://llvm.org/viewvc/<wbr>llvm-project?view=revision&<wbr>revision=253328</a> by Oliver Sstannard, CC-ed)</div><div><br></div><div>The error comes from lib/MC/ELFObjectWriter.<wbr>cpp </div><div>and it disappears with -O0 or -O2 or -no-integrated-as</div><div><br></div><div>Thanks! </div><div><br></div><div>--kcc </div></div>
</blockquote></div><br></div>