Page MenuHomeFreeBSD

Expose symbols in lib/libclang_rt/profile to fix --coverage...
ClosedPublic

Authored by ngie on Jan 13 2017, 10:10 AM.
Tags
None
Referenced Files
Unknown Object (File)
Jan 6 2024, 12:43 PM
Unknown Object (File)
Jan 6 2024, 12:43 PM
Unknown Object (File)
Dec 28 2023, 9:18 AM
Unknown Object (File)
Dec 20 2023, 12:21 AM
Unknown Object (File)
Nov 21 2023, 11:00 AM
Unknown Object (File)
Nov 16 2023, 2:36 PM
Unknown Object (File)
Nov 15 2023, 8:16 AM
Unknown Object (File)
Nov 13 2023, 8:15 AM

Details

Summary

Expose symbols in lib/libclang_rt/profile to fix --coverage...

This fixes --coverage with libclang_rt.

MFC after: 1 month
Sponsored by: Dell EMC Isilon

Test Plan

Generating coverage numbers now works with zero hacks using the system
compiler/library, e.g. as described in my mailing list thread back in
2015, titled, "A better way to get runtime coverage with libprofile_rt
(from compiler_rt) / gcov?"
https://lists.freebsd.org/pipermail/freebsd-toolchain/2015-April/001669.html

$ make -s obj; make -s depend; make -s all; make get-coverage
===> lib (obj)
===> bin (obj)
===> lib (depend)
===> bin (depend)
===> lib (all)
===> bin (all)
LD_LIBRARY_PATH=/usr/obj/home/ngie/nfs/git/scratch/coverage-with-shared-libs-freebsd/lib /usr/obj/home/ngie/nfs/git/scratch/coverage-with-shared-libs-freebsd/bin/foo
This is foo
lcov --capture --directory /usr/obj/home/ngie/nfs/git/scratch/coverage-with-shared-libs-freebsd --output-file /usr/obj/home/ngie/nfs/git/scratch/coverage-with-shared-libs-freebsd/coverage.info
Capturing coverage data from /usr/obj/home/ngie/nfs/git/scratch/coverage-with-shared-libs-freebsd
Found gcov version: 4.2.1
Scanning /usr/obj/home/ngie/nfs/git/scratch/coverage-with-shared-libs-freebsd for .gcda files ...
Found 2 data files in /usr/obj/home/ngie/nfs/git/scratch/coverage-with-shared-libs-freebsd
Processing lib/foo.gcda
/usr/obj/home/ngie/nfs/git/scratch/coverage-with-shared-libs-freebsd/lib/foo.gcno:version '402*', prefer '402p'
/usr/obj/home/ngie/nfs/git/scratch/coverage-with-shared-libs-freebsd/lib/foo.gcda:version '402*', prefer version '402p'
Processing bin/foo.gcda
/usr/obj/home/ngie/nfs/git/scratch/coverage-with-shared-libs-freebsd/bin/foo.gcno:version '402*', prefer '402p'
/usr/obj/home/ngie/nfs/git/scratch/coverage-with-shared-libs-freebsd/bin/foo.gcda:version '402*', prefer version '402p'
Finished .info-file creation
genhtml /usr/obj/home/ngie/nfs/git/scratch/coverage-with-shared-libs-freebsd/coverage.info --output-directory output
Reading data file /usr/obj/home/ngie/nfs/git/scratch/coverage-with-shared-libs-freebsd/coverage.info
Found 2 entries.
Found common filename prefix "/home/ngie/nfs/git/scratch/coverage-with-shared-libs-freebsd"
Writing .css and .png files.
Generating output.
Processing file bin/foo.c
Processing file lib/foo.c
Writing directory view page.
Overall coverage rate:
  lines......: 75.0% (3 of 4 lines)
  functions..: 100.0% (2 of 2 functions)
$

Diff Detail

Repository
rS FreeBSD src repository - subversion
Lint
Lint Not Applicable
Unit
Tests Not Applicable

Event Timeline

ngie retitled this revision from to Expose all of the symbols in profile_rt.
ngie updated this object.
ngie edited the test plan for this revision. (Show Details)
ngie added a reviewer: dim.
ngie added subscribers: markj, bdrewery, benno, emaste.
ngie added a reviewer: emaste.
ngie removed a subscriber: emaste.

As far as I can tell, upstream not setting the visibility flags for the .c files in the profile library is some sort of mistake. It looks like the intent has always been to hide all symbols in all of the compiler-rt libraries, wherever possible.

Also, I am still unsure as to what this fixes, exactly. Why would something external want to reference internal symbols in this profiling library?

In D9168#189733, @dim wrote:

As far as I can tell, upstream not setting the visibility flags for the .c files in the profile library is some sort of mistake. It looks like the intent has always been to hide all symbols in all of the compiler-rt libraries, wherever possible.

Also, I am still unsure as to what this fixes, exactly. Why would something external want to reference internal symbols in this profiling library?

Let me expand on this.

If you look at the static libraries, the port copy of libprofile_rt's APIs are public, whereas the base system copy of libprofile_rt's APIs are private:

Base system copy:

% objdump -t /usr/lib/clang/3.9.1/lib/freebsd/libclang_rt.profile-x86_64.a | grep llvm_gcda
0000000000000880 g     F .text  0000000000000376 .hidden llvm_gcda_emit_arcs
0000000000000420 g     F .text  0000000000000454 .hidden llvm_gcda_emit_function
00000000000010b0 g     F .text  000000000000016f .hidden llvm_gcda_end_file
0000000000000400 g     F .text  000000000000001e .hidden llvm_gcda_increment_indirect_counter
0000000000000000 g     F .text  00000000000003fb .hidden llvm_gcda_start_file
0000000000000c00 g     F .text  00000000000004a6 .hidden llvm_gcda_summary_info
...

The port copy:

% objdump -t /usr/local/llvm38/lib/clang/3.8.1/lib/freebsd/libclang_rt.profile-x86_64.a | grep llvm_gcda
00000000000008e0 g     F .text  0000000000000348 llvm_gcda_emit_arcs
00000000000004b0 g     F .text  0000000000000424 llvm_gcda_emit_function
00000000000013b0 g     F .text  000000000000019a llvm_gcda_end_file
0000000000000490 g     F .text  000000000000001e llvm_gcda_increment_indirect_counter
0000000000000000 g     F .text  000000000000048e llvm_gcda_start_file
0000000000000c30 g     F .text  000000000000077a llvm_gcda_summary_info

These symbols being hidden makes it impossible for the clang toolchain to use them when the user specifies --coverage, e.g.

% make CC=cc
===> lib (all)
===> bin (all)
cc -O2 -pipe -I/home/ngie/nfs/git/scratch/coverage-with-shared-libs-freebsd/lib --coverage -g -std=gnu99 -fstack-protector-strong -Qunused-arguments  -L/usr/obj/home/ngie/nfs/git/scratch/coverage-with-shared-libs-freebsd/lib -Wl,-rpath-link,/usr/obj/home/ngie/nfs/git/scratch/coverage-with-shared-libs-freebsd/lib -o foo.full foo.o  -lfoo
/usr/bin/ld: foo.full: hidden symbol `llvm_gcda_emit_arcs' in /usr/bin/../lib/clang/3.9.1/lib/freebsd/libclang_rt.profile-x86_64.a(GCDAProfiling.o) is referenced by DSO
/usr/bin/ld: final link failed: Nonrepresentable section on output
cc: error: linker command failed with exit code 1 (use -v to see invocation)
*** Error code 1

Stop.
make[1]: stopped in /home/ngie/nfs/git/scratch/coverage-with-shared-libs-freebsd/bin
*** Error code 1

Stop.
make: stopped in /home/ngie/nfs/git/scratch/coverage-with-shared-libs-freebsd
%

vs

% make CC=/usr/local/bin/clang38                                                                                                                                                                            
===> lib (all)
===> bin (all)
/usr/local/bin/clang38 -O2 -pipe -I/home/ngie/nfs/git/scratch/coverage-with-shared-libs-freebsd/lib --coverage -g -std=gnu99 -fstack-protector-strong -Qunused-arguments  -L/usr/obj/home/ngie/nfs/git/scratch/coverage-with-shared-libs-freebsd/lib -Wl,-rpath-link,/usr/obj/home/ngie/nfs/git/scratch/coverage-with-shared-libs-freebsd/lib -o foo.full foo.o  -lfoo
objcopy --only-keep-debug foo.full foo.debug
objcopy --strip-debug --add-gnu-debuglink=foo.debug  foo.full foo
%

We have been working around this symbol issue for 4 releases now at work by using a specially configured/built copy of libprofile_rt because we weren't aware of the symbol hiding. Once I remove the symbol hiding, things just work with the copy of clang in base with this library.

In D9168#190694, @ngie wrote:

...

We have been working around this symbol issue for 4 releases now at work by using a specially configured/built copy of libprofile_rt because we weren't aware of the symbol hiding. Once I remove the symbol hiding, things just work with the copy of clang in base with this library.

profile_rt isn't the only library -- it looks like everything except asan-preinit is exposed publicly:

$ for i in /usr/local/llvm39/lib/clang/3.9.1/lib/freebsd/*.a; do objdump -t $i | grep -q hidden && echo $i || echo not $i; done
not /usr/local/llvm39/lib/clang/3.9.1/lib/freebsd/libclang_rt.asan-preinit-x86_64.a
/usr/local/llvm39/lib/clang/3.9.1/lib/freebsd/libclang_rt.asan-x86_64.a
/usr/local/llvm39/lib/clang/3.9.1/lib/freebsd/libclang_rt.asan_cxx-x86_64.a
/usr/local/llvm39/lib/clang/3.9.1/lib/freebsd/libclang_rt.builtins-x86_64.a
/usr/local/llvm39/lib/clang/3.9.1/lib/freebsd/libclang_rt.dd-x86_64.a
/usr/local/llvm39/lib/clang/3.9.1/lib/freebsd/libclang_rt.lsan-x86_64.a
/usr/local/llvm39/lib/clang/3.9.1/lib/freebsd/libclang_rt.profile-x86_64.a
/usr/local/llvm39/lib/clang/3.9.1/lib/freebsd/libclang_rt.safestack-x86_64.a
/usr/local/llvm39/lib/clang/3.9.1/lib/freebsd/libclang_rt.stats-x86_64.a
/usr/local/llvm39/lib/clang/3.9.1/lib/freebsd/libclang_rt.stats_client-x86_64.a
/usr/local/llvm39/lib/clang/3.9.1/lib/freebsd/libclang_rt.tsan-x86_64.a
/usr/local/llvm39/lib/clang/3.9.1/lib/freebsd/libclang_rt.tsan_cxx-x86_64.a
/usr/local/llvm39/lib/clang/3.9.1/lib/freebsd/libclang_rt.ubsan_standalone-x86_64.a
/usr/local/llvm39/lib/clang/3.9.1/lib/freebsd/libclang_rt.ubsan_standalone_cxx-x86_64.a
%
In D9168#190768, @ngie wrote:
In D9168#190694, @ngie wrote:

...

We have been working around this symbol issue for 4 releases now at work by using a specially configured/built copy of libprofile_rt because we weren't aware of the symbol hiding. Once I remove the symbol hiding, things just work with the copy of clang in base with this library.

profile_rt isn't the only library -- it looks like everything except asan-preinit is exposed publicly:

$ for i in /usr/local/llvm39/lib/clang/3.9.1/lib/freebsd/*.a; do objdump -t $i | grep -q hidden && echo $i || echo not $i; done
not /usr/local/llvm39/lib/clang/3.9.1/lib/freebsd/libclang_rt.asan-preinit-x86_64.a
/usr/local/llvm39/lib/clang/3.9.1/lib/freebsd/libclang_rt.asan-x86_64.a
/usr/local/llvm39/lib/clang/3.9.1/lib/freebsd/libclang_rt.asan_cxx-x86_64.a
/usr/local/llvm39/lib/clang/3.9.1/lib/freebsd/libclang_rt.builtins-x86_64.a
/usr/local/llvm39/lib/clang/3.9.1/lib/freebsd/libclang_rt.dd-x86_64.a
/usr/local/llvm39/lib/clang/3.9.1/lib/freebsd/libclang_rt.lsan-x86_64.a
/usr/local/llvm39/lib/clang/3.9.1/lib/freebsd/libclang_rt.profile-x86_64.a
/usr/local/llvm39/lib/clang/3.9.1/lib/freebsd/libclang_rt.safestack-x86_64.a
/usr/local/llvm39/lib/clang/3.9.1/lib/freebsd/libclang_rt.stats-x86_64.a
/usr/local/llvm39/lib/clang/3.9.1/lib/freebsd/libclang_rt.stats_client-x86_64.a
/usr/local/llvm39/lib/clang/3.9.1/lib/freebsd/libclang_rt.tsan-x86_64.a
/usr/local/llvm39/lib/clang/3.9.1/lib/freebsd/libclang_rt.tsan_cxx-x86_64.a
/usr/local/llvm39/lib/clang/3.9.1/lib/freebsd/libclang_rt.ubsan_standalone-x86_64.a
/usr/local/llvm39/lib/clang/3.9.1/lib/freebsd/libclang_rt.ubsan_standalone_cxx-x86_64.a
%

In retrospect, these CFLAGS are incorrect -- the libraries already specify visibility attributes via COMPILER_RT_VISIBILITY, etc.

I'm just going to delete the lines and see what happens.

In D9168#190769, @ngie wrote:

...

I'm just going to delete the lines and see what happens.

Here are the rationale for the -fvisibility lines, which have been carried on to today:

$ svn log -c 215129
------------------------------------------------------------------------
r215129 | ed | 2010-11-11 08:53:25 -0800 (Thu, 11 Nov 2010) | 7 lines

Set symbol visibility to hidden.

Not doing so may cause all sorts of random libraries to expose
libcompiler_rt's functions, which should of course not be done.

Discussed with: kan, kib

------------------------------------------------------------------------

libcompiler_rt used to be installed to /usr/lib, so this rationale made sense, however -- all of the libclang_rt libraries are private to clang's lib directory (you have to explicitly add the path to LDFLAGS, which is wrong in so many ways), so this is no longer an issue.

ngie edited edge metadata.

Remove -fvisibility*=hidden flags since libclang_rt is private to clang

ngie retitled this revision from Expose all of the symbols in profile_rt to Expose all of the symbols in lib/libclang_rt/....Jan 26 2017, 11:50 PM
ngie updated this object.

Ping?

I'm still not sure about this. I did an analysis of how upstream builds compiler-rt, and they are definitely using -fvisibility-inlines-hidden for all C++ sources (for C sources this flag is not functional). I don't think you ever want to export addresses of inline functions.

Upstream also uses -fvisibility=hidden for the following parts of compiler-rt:

  • lib/sanitizer_common
  • lib/interception
  • lib/asan
  • lib/ubsan
  • lib/stats
  • lib/lsan
  • lib/safestack

In fact the only parts where -fvisibility is not used, are:

  • lib/builtins
  • lib/profile

I'm going to take a look at your previous diff now.

dim edited reviewers, added: ngie; removed: dim.
dim removed rS FreeBSD src repository - subversion as the repository for this revision.

Let's use this instead. I just tried building your coverage-with-shared-libs-freebsd project with it, and it worked fine.

In D9168#193461, @dim wrote:

Let's use this instead. I just tried building your coverage-with-shared-libs-freebsd project with it, and it worked fine.

Thank you for the counter-proposal!

Should the builtins library be handled this way as well?

ngie retitled this revision from Expose all of the symbols in lib/libclang_rt/... to Expose symbols in lib/libclang_rt/profile to fix --coverage....Jan 28 2017, 11:14 PM
ngie updated this object.
ngie edited edge metadata.
In D9168#193606, @ngie wrote:
In D9168#193461, @dim wrote:

Let's use this instead. I just tried building your coverage-with-shared-libs-freebsd project with it, and it worked fine.

Thank you for the counter-proposal!

Please commandeer the revision back to yourself, and then you can commit it :)

Should the builtins library be handled this way as well?

Yes, maybe, though nobody yet complained about any symbols being hidden. @emaste, what's your opinion on this?

ngie edited reviewers, added: dim; removed: ngie.