Summary:
Currently, the GPU iterates through all of the present symbols and
copies them by prefix. This is inefficient as it requires a lot of small
high-latency data transfers rather than a few large ones. Additionally,
we force every single profiling symbol to have protected visibility.
This means potentially hundreds of unnecessary symbols in the symbol
table.
This PR changes the interface to move towards the start / stop section
handling. AMDGPU supports this natively as an ELF target, so we need
little changes. Instead of overriding visibility, we use a single table
to define the bounds that we can obtain with one contiguous load.
Using a table interface should also work for the in-progress HIP
implementation for this, as it wraps the start / stop sections into
standard void pointers which will be inside of an already mapped region
of memory, so they should be accessible from the HIP API.
NVPTX is more difficult as it is an ELF platform without this support. I
have hooked up the 'Other' handling to work around this, but even then
it's a bit of a stretch. I could remove this support here, but I wanted
to demonstrate that we can share the ABI. However, NVPTX will only work
if we force LTO and change the backend to emit variables in the same
TL;DR, we now do this:
```c
struct { start1, stop1, start2, stop2, start3, stop3, version; } device;
struct host = DtoH(lookup("device"));
counters = DtoH(host.stop - host.start)
version = DtoH(host.version);
```
Adds a flag COMPILER_RT_PROFILE_BAREMETAL, which disables the parts of
the profile runtime which require a filesystem or malloc. This minimal
library only requires string.h from the C library.
This is useful for profiling or code coverage of baremetal images, which
don't have filesystem APIs, and might not have malloc configured (or
have limited heap space).
Expected usage:
- Add code to your project to call
`__llvm_profile_get_size_for_buffer()` and
`__llvm_profile_write_buffer()` to write the profile data to a buffer in
memory, and then copy that data off the device using target-specific
tools.
- If you're using a linker script, set up your linker script to map the
profiling and coverage input sections to corresponding output sections
with the same name, and mark them KEEP. `__llvm_covfun` and
`__llvm_covmap` are non-allocatable, `__llvm_prf_names` is read-only
allocatable, and `__llvm_prf_cnts` and `__llvm_prf_data` are read-write
allocatable.
- The resulting data is in same format as the non-baremetal profiles.
There's some room for improvement here in the future for doing profiling
and code coverage for baremetal. If we revised the profiling format, and
introduced some additional host tooling, we could move some of the
metadata into non-allocated sections, and construct the profraw file on
the host. But this patch is sufficient for some use-cases.
This function is always examining its own ELF headers in memory, but it
was trying to use conditions between examining files or memory, and it
wasn't accounting for LOAD offsets at runtime. This is especially bad if
a loaded segment has additional padding that's not in the file offsets.
Now we do a first scan of the program headers to figure out the runtime
base address based on `PT_PHDR` and/or `PT_DYNAMIC` (else assume zero),
similar to libc's `do_start`. Then each `PT_NOTE` pointer is simply the
base plus the segments's `pt_vaddr`, which includes LOAD offsets.
Fixes#114605
This PR registers the writeout and reset functions for `gcov` for all
modules in the PGO runtime, instead of registering them
using global constructors in each module. The change is made for AIX
only, but the same mechanism works on Linux on Power.
When registering such functions using global constructors in each module
without `-ffunction-sections`, the AIX linker cannot garbage collect
unused undefined symbols, because such symbols are grouped in the same
section as the `__sinit` symbol. Keeping such undefined symbols causes
link errors (see test case
https://github.com/llvm/llvm-project/pull/108570/files#diff-500a7e1ba871e1b6b61b523700d5e30987900002add306e1b5e4972cf6d5a4f1R1
for this scenario). This PR implements the initialization in the
runtime, hence avoiding introducing `__sinit` into each module.
The implementation adds a new global variable `__llvm_covinit_functions`
to each module. This new global variable contains the function pointers
to the `Writeout` and `Reset` functions. `__llvm_covinit_functions`'s
section is the named section `__llvm_covinit`. The linker will aggregate
all the `__llvm_covinit` sections from each module
to form one single named section in the final binary. The pair of
functions
```
const __llvm_gcov_init_func_struct *__llvm_profile_begin_covinit();
const __llvm_gcov_init_func_struct *__llvm_profile_end_covinit();
```
are implemented to return the start and end address of this named
section in the final binary, and they are used in function
```
__llvm_profile_gcov_initialize()
```
(which is a constructor function in the runtime) so the runtime knows
the addresses of all the `Writeout` and `Reset` functions from all the
modules.
One noticeable implementation detail relevant to AIX is that to preserve
the `__llvm_covinit` from the linker's garbage collection, a `.ref`
pseudo instruction is inserted into them, referring to the section that
contains the `__llvm_gcov_ctr` variables, which are used in the
instrumented code. The `__llvm_gcov_ctr` variables did not belong to
named sections before, but this PR added them to the
`__llvm_gcov_ctr_section` named section, so we can add a `.ref` pseudo
instruction that refers to them in the `__llvm_covinit` section.
Currently, WebAssembly/WASI target does not provide direct support for
code coverage.
This patch set fixes several issues to unlock the feature. The main
changes are:
1. Port `compiler-rt/lib/profile` to WebAssembly/WASI.
2. Adjust profile metadata sections for Wasm object file format.
- [CodeGen] Emit `__llvm_covmap` and `__llvm_covfun` as custom sections
instead of data segments.
- [lld] Align the interval space of custom sections at link time.
- [llvm-cov] Copy misaligned custom section data if the start address is
not aligned.
- [llvm-cov] Read `__llvm_prf_names` from data segments
3. [clang] Link with profile runtime libraries if requested
See each commit message for more details and rationale.
This is part of the effort to add code coverage support in Wasm target
of Swift toolchain.
New change on top of [reviewed
patch](https://github.com/llvm/llvm-project/pull/81691) are [in commits
after this
one](d0757f46b3).
Previous commits are restored from the remote branch with timestamps.
1. Fix build breakage for non-ELF platforms, by defining the missing
functions {`__llvm_profile_begin_vtables`, `__llvm_profile_end_vtables`,
`__llvm_profile_begin_vtabnames `, `__llvm_profile_end_vtabnames`}
everywhere.
* Tested on mac laptop (for darwins) and Windows. Specifically,
functions in `InstrProfilingPlatformWindows.c` returns `NULL` to make it
more explicit that type prof isn't supported; see comments for the
reason.
* For the rest (AIX, other), mostly follow existing examples (like this
[one](f95b2f1acf))
2. Rename `__llvm_prf_vtabnames` -> `__llvm_prf_vns` for shorter section
name, and make returned pointers
[const](a825d2a4ec (diff-4de780ce726d76b7abc9d3353aef95013e7b21e7bda01be8940cc6574fb0b5ffR120-R121))
**Original Description**
* Raw profile format
- Header: records the byte size of compressed vtable names, and the
number of profiled vtable entries (call it `VTableProfData`). Header
also records padded bytes of each section.
- Payload: adds a section for compressed vtable names, and a section to
store `VTableProfData`. Both sections are padded so the size is a
multiple of 8.
* Indexed profile format
- Header: records the byte offset of compressed vtable names.
- Payload: adds a section to store compressed vtable names. This section
is used by `llvm-profdata` to show the list of vtables profiled for an
instrumented site.
[The originally reviewed
patch](https://github.com/llvm/llvm-project/pull/66825) will have
profile reader/write change and llvm-profdata change.
- To ensure this PR has all the necessary profile format change along
with profile version bump, created a copy of the originally reviewed
patch in https://github.com/llvm/llvm-project/pull/80761. The copy
doesn't have profile format change, but it has the set of tests which
covers type profile generation, profile read and profile merge. Tests
pass there.
rfc in
https://discourse.llvm.org/t/rfc-dynamic-type-profiling-and-optimizations-in-llvm/74600
---------
Co-authored-by: modiking <modiking213@gmail.com>
* Raw profile format
- Header: records the byte size of compressed vtable names, and the
number of profiled vtable entries (call it `VTableProfData`). Header
also records padded bytes of each section.
- Payload: adds a section for compressed vtable names, and a section to
store `VTableProfData`. Both sections are padded so the size is a
multiple of 8.
* Indexed profile format
- Header: records the byte offset of compressed vtable names.
- Payload: adds a section to store compressed vtable names. This section
is used by `llvm-profdata` to show the list of vtables profiled for an
instrumented site.
[The originally reviewed
patch](https://github.com/llvm/llvm-project/pull/66825) will have
profile reader/write change and llvm-profdata change.
- To ensure this PR has all the necessary profile format change along
with profile version bump, created a copy of the originally reviewed
patch in https://github.com/llvm/llvm-project/pull/80761. The copy
doesn't have profile format change, but it has the set of tests which
covers type profile generation, profile read and profile merge. Tests
pass there.
rfc in
https://discourse.llvm.org/t/rfc-dynamic-type-profiling-and-optimizations-in-llvm/74600
---------
Co-authored-by: modiking <modiking213@gmail.com>
Part 1 of 3. This includes the LLVM back-end processing and profile
reading/writing components. compiler-rt changes are included.
Differential Revision: https://reviews.llvm.org/D138846
This seems to cause Clang to crash, see comments on the code review. Reverting
until the problem can be investigated.
> Part 1 of 3. This includes the LLVM back-end processing and profile
> reading/writing components. compiler-rt changes are included.
>
> Differential Revision: https://reviews.llvm.org/D138846
This reverts commit a50486fd736ab2fe03fcacaf8b98876db77217a7.
Part 1 of 3. This includes the LLVM back-end processing and profile
reading/writing components. compiler-rt changes are included.
Differential Revision: https://reviews.llvm.org/D138846
On AIX, the build-id can be embedded in a binary using the -mxcoff-build-id
compiler option. When present, the build id is stored as an ascii string at the
beginning of the string table in the loader section of the XCOFF file.
Reviewed By: stephenpeckham, daltenty
Differential Revision: https://reviews.llvm.org/D146976
1) Use a static array of pointer to retain the dummy vars.
2) Associate liveness of the array with that of the runtime hook variable
__llvm_profile_runtime.
3) Perform the runtime initialization through the runtime hook variable.
4) Preserve the runtime hook variable using the -u linker flag.
Reviewed By: hubert.reinterpretcast
Differential Revision: https://reviews.llvm.org/D136192
This patch switches the PGO implementation on AIX from using the runtime
registration-based section tracking to the __start_SECNAME/__stop_SECNAME
based. In order to enable the recognition of __start_SECNAME/__stop_SECNAME
symbols in the AIX linker, the -bdbg:namedsects:ss needs to be used.
Reviewed By: jsji, MaskRay, davidxl
Differential Revision: https://reviews.llvm.org/D124857
Existing code tended to assume that counters had type `uint64_t` and
computed size from the number of counters. Fix this code to directly
compute the counters size in number of bytes where possible. When the
number of counters is needed, use `__llvm_profile_counter_entry_size()`
or `getCounterTypeSize()`. In a later diff these functions will depend
on the profile mode.
Change the meaning of `DataSize` and `CountersSize` to make them more clear.
* `DataSize` (`CountersSize`) - the size of the data (counter) section in bytes.
* `NumData` (`NumCounters`) - the number of data (counter) entries.
Reviewed By: kyulee
Differential Revision: https://reviews.llvm.org/D116179
This patch adds support to read all the PT_NOTE segments in the
executable to find the binary ids. Previously, it was only reading
the first PT_NOTE segment, and this was missing the cases where
binary id is in the following segments. As a result, binary-id.c
and binary-id-padding.c test were failing in the following cases:
1) sanitizer-x86_64-linux bot
https://lab.llvm.org/staging/#/builders/97
2) OpenSuse Tumbleweed
https://github.com/llvm/llvm-project/issues/52695
Differential Revision: https://reviews.llvm.org/D115830
Some tests with binary IDs would fail with error: no profile can be merged.
This is because raw profiles could have unaligned headers when emitting binary
IDs. This means padding should be emitted after binary IDs are emitted to
ensure everything else is aligned. This patch adds padding after each binary ID
to ensure the next binary ID size is 8-byte aligned. This also adds extra
checks to ensure we aren't reading corrupted data when printing binary IDs.
Differential Revision: https://reviews.llvm.org/D110365
Some tests with binary IDs would fail with error: no profile can be merged.
This is because raw profiles could have unaligned headers when emitting binary
IDs. This means padding should be emitted after binary IDs are emitted to
ensure everything else is aligned. This patch accounts for that padding in
__llvm_write_binary_ids.
Differential Revision: https://reviews.llvm.org/D110188
This patch adds static keyword to internal functions that write
binary id to restrict visibility to the file that they are declared.
Differential Revision: https://reviews.llvm.org/D108154
The Solaris buildbots have been broken for some time by the unconditional
use of `NT_GNU_BUILD_ID`, e.g. Solaris/sparcv9
<https://lab.llvm.org/staging/#/builders/50/builds/4910> and Solaris/amd64
<https://lab.llvm.org/staging/#/builders/101/builds/3751>. Being a GNU
extension, it is not defined in `<sys/elf.h>`. However, providing a
fallback definition doesn't help because the code also relies on
`__ehdr_start`, another unportable GNU extension that most likely never
will be implemented in Solaris `ld`. Besides, there's reallly no point in
supporting build ids since they aren't used on Solaris at all.
This patch fixes this by making the relevant code conditional on the
definition of `NT_GNU_BUILD_ID`.
Tested on `amd64-pc-solaris2.11` and `sparcv9-sun-solaris2.11`.
Differential Revision: https://reviews.llvm.org/D107556
Fixes PR51331. On FreeBSD, the elf headers don't (yet) provide the
ElfW(type) macro. However, there is a similar set of macros in the
<sys/elf-generic.h> header, of which `__ElfN(type)` exactly matches the
indended purpose.
Reviewed By: gulfem
Differential Revision: https://reviews.llvm.org/D107388
Revert "[profile] Change linkage type of a compiler-rt func"
This reverts commits f984ac2715f71c38a7872fa2c2ad535b3d4fa285 and
467c7191249b76abff33853b1692a77f327c2422 because it broke some builds.
This patch changes the linkage type of a compiler-rt func
(__llvm_write_binary_ids) to fix the sanitizer-windows bot
build issue introduced in change f984ac271.
The issue is as the following:
C:\b\slave\sanitizer-windows\llvm-project\compiler-rt\lib\profile\InstrProfilingInternal.h(201):
error C2496: '__llvm_write_binary_ids': 'selectany' can only be applied
to data items with external linkage
They were added so that if no metadata section is present,
`__start_llvm_prf_*` references would not cause "undefined symbol"
errors. By switching to undefined weak symbols in D96936, the dummy
sections are not needed.
This patch is also needed to work around
https://sourceware.org/bugzilla/show_bug.cgi?id=27490
Differential Revision: https://reviews.llvm.org/D97648
To make a kind of metadata section usage work, we want to drop the
`__start_/__stop_ references retain C identifier name sections` rule from LLD (see D96914).
If an application has no `__llvm_prf_data` input section surviving --gc-sections,
LLD will error for undefined hidden `{__start_,__stop_}__llvm_prf_*` from `libclang_rt.profile-*`.
Other `__llvm_prf_*` sections have similar issues.
Making the references weak can address the problem.
This probably enables the opportunity to drop zero size dummy sections in `InstrProfilingPlatformLinux.c`.
Reviewed By: davidxl
Differential Revision: https://reviews.llvm.org/D96936
D14468 added these dummy sections. This patch adds `__attribute__((used))` so
that when compiled by GCC>=11 or (expected, D96838) Clang>=13 on some ELF platforms,
these sections will get SHF_GNU_RETAIN to make sure they will not be discarded
by ld --gc-sections.
We are trying to get rid of LLD's "__start_/__stop_ references retain C identifier name sections" rule.
If LLD drops the rule in the future (we will retain compatibility for `__llvm_prf_*` for a while),
`__llvm_prf_*` will need to have the SHF_GNU_RETAIN flag, otherwise:
```
// __llvm_prf_cnts/__llvm_prf_data usually exist, but {names,vnds} may not exist.
// Such diagnostics will happen with {cnts,data} as well if no input object file is instrumented.
% clang++ -fprofile-generate a.cc -fuse-ld=lld -Wl,--gc-sections
ld.lld: error: undefined hidden symbol: __start___llvm_prf_names
>>> referenced by InstrProfilingPlatformLinux.c
>>> InstrProfilingPlatformLinux.c.o:(__llvm_profile_begin_names) in archive /tmp/RelA/lib/clang/13.0.0/lib/linux/libclang_rt.profile-x86_64.a
...
```
Differential Revision: https://reviews.llvm.org/D96902
Currently, several InstrProf tests `FAIL` on Solaris (both sparc and x86):
Profile-i386 :: Posix/instrprof-visibility.cpp
Profile-i386 :: instrprof-merging.cpp
Profile-i386 :: instrprof-set-file-object-merging.c
Profile-i386 :: instrprof-set-file-object.c
On sparc there's also
Profile-sparc :: coverage_comments.cpp
The failure mode is always the same:
error: /var/llvm/local-amd64/projects/compiler-rt/test/profile/Profile-i386/Posix/Output/instrprof-visibility.cpp.tmp: Failed to load coverage: Malformed coverage data
The error is from `llvm/lib/ProfileData/Coverage/CoverageMappingReader.cpp`
(`loadBinaryFormat`), l.926:
InstrProfSymtab ProfileNames;
std::vector<SectionRef> NamesSectionRefs = *NamesSection;
if (NamesSectionRefs.size() != 1)
return make_error<CoverageMapError>(coveragemap_error::malformed);
where .size() is 2 instead.
Looking at the executable, I find (with `elfdump -c -N __llvm_prf_names`):
Section Header[15]: sh_name: __llvm_prf_names
sh_addr: 0x8053ca5 sh_flags: [ SHF_ALLOC ]
sh_size: 0x86 sh_type: [ SHT_PROGBITS ]
sh_offset: 0x3ca5 sh_entsize: 0
sh_link: 0 sh_info: 0
sh_addralign: 0x1
Section Header[31]: sh_name: __llvm_prf_names
sh_addr: 0x8069998 sh_flags: [ SHF_WRITE SHF_ALLOC ]
sh_size: 0 sh_type: [ SHT_PROGBITS ]
sh_offset: 0x9998 sh_entsize: 0
sh_link: 0 sh_info: 0
sh_addralign: 0x1
Unlike GNU `ld` (which primarily operates on section names) the Solaris
linker, following the ELF spirit, only merges input sections into an output
section if both section name and section flags match, so two separate
sections are maintained.
The read-write one comes from `lib/clang/12.0.0/lib/sunos/libclang_rt.profile-i386.a(InstrProfilingPlatformLinux.c.o)`
while the read-only one is generated by
`llvm/lib/Transforms/Instrumentation/InstrProfiling.cpp` (`InstrProfiling::emitNameData`)
at l.1004 where `isConstant = true`.
The easiest way to avoid the mismatch is to change the definition in
`compiler-rt/lib/profile/InstrProfilingPlatformLinux.c` to `const`.
This fixes all failures observed.
Tested on `amd64-pc-solaris2.11`, `sparcv9-sun-solaris2.11`, and
`x86_64-pc-linux-gnu`.
Differential Revision: https://reviews.llvm.org/D85116
This reverts commit 69c5ff4668cd4d1bfb6b45d71e15c12e3a23ae05.
This reverts commit 603d58b5e49c76e4a2e5bf1450b71b100a3396ba.
This reverts commit ba10bedf5631eda3a17df428c88451c754633d23.
This reverts commit 39b3c41b65302a969fa5507402976a255a07c158.
The !associated metadata may be attached to a global object declaration
with a single argument that references another global object. This
metadata prevents discarding of the global object in linker GC unless
the referenced object is also discarded.
Furthermore, when a function symbol is discarded by the linker, setting
up !associated metadata allows linker to discard counters, data and
values associated with that function symbol. This is not possible today
because there's metadata to guide the linker. This approach is also used
by other instrumentations like sanitizers.
Note that !associated metadata is only supported by ELF, it does not have
any effect on non-ELF targets.
Differential Revision: https://reviews.llvm.org/D76802
The !associated metadata may be attached to a global object declaration
with a single argument that references another global object. This
metadata prevents discarding of the global object in linker GC unless
the referenced object is also discarded.
Furthermore, when a function symbol is discarded by the linker, setting
up !associated metadata allows linker to discard counters, data and
values associated with that function symbol. This is not possible today
because there's metadata to guide the linker. This approach is also used
by other instrumentations like sanitizers.
Note that !associated metadata is only supported by ELF, it does not have
any effect on non-ELF targets.
Differential Revision: https://reviews.llvm.org/D76802
r355343 was landed and was reverted in r355363 due to build breakage.
This patch adds Linux/Windows support on top of r355343.
In this patch, Darwin should be working with testing case. Linux should be working,
I will enable the testing case in a follwup diff. Windows/Other should be building.
Correct implementation for Other platforms will be added.
Thanks David for reviewing the original diff, helping me with issues on Linux, and
giving suggestions for adding support for Other platforms.
llvm-svn: 355701
Summary:
The motivating use case is eliminating duplicate profile data registered
for the same inline function in two object files. Before this change,
users would observe multiple symbol definition errors with VC link, but
links with LLD would succeed.
Users (Mozilla) have reported that PGO works well with clang-cl and LLD,
but when using LLD without this static registration, we would get into a
"relocation against a discarded section" situation. I'm not sure what
happens in that situation, but I suspect that duplicate, unused profile
information was retained. If so, this change will reduce the size of
such binaries with LLD.
Now, Windows uses static registration and is in line with all the other
platforms.
Reviewers: davidxl, wmi, inglorion, void, calixte
Subscribers: mgorny, krytarowski, eraman, fedor.sergeev, hiraditya, #sanitizers, dmajor, llvm-commits
Tags: #sanitizers, #llvm
Differential Revision: https://reviews.llvm.org/D57929
llvm-svn: 353547
to reflect the new license.
We understand that people may be surprised that we're moving the header
entirely to discuss the new license. We checked this carefully with the
Foundation's lawyer and we believe this is the correct approach.
Essentially, all code in the project is now made available by the LLVM
project under our new license, so you will see that the license headers
include that license only. Some of our contributors have contributed
code under our old license, and accordingly, we have retained a copy of
our old license notice in the top-level files in each project and
repository.
llvm-svn: 351636
Summary:
NetBSD uses typical UNIX interfaces.
All tests pass except instrprof-dlopen-dlclose-gcov.test, as there
is not supported semantics of atexit(3) in dlopen(3)ed+dlclose(3)d
DSO.
NetBSD also ships an older version of LLVM profile (ABI v.2 predating
ABI v.4 in upstream version) inside libc. That copy has been manually
removed during the porting and testing process of the upstream version
to NetBSD. Otherwise there were conflicts between them two.
Reviewers: joerg, vitalybuka, vsk
Subscribers: srhines, fedor.sergeev, llvm-commits, mgorny, #sanitizers
Tags: #sanitizers
Differential Revision: https://reviews.llvm.org/D55997
llvm-svn: 349994
This ports the profiling runtime on Fuchsia and enables the
instrumentation. Unlike on other platforms, Fuchsia doesn't use
files to dump the instrumentation data since on Fuchsia, filesystem
may not be accessible to the instrumented process. We instead use
the data sink to pass the profiling data to the system the same
sanitizer runtimes do.
Differential Revision: https://reviews.llvm.org/D47208
llvm-svn: 337881
This includes a few nice bits of refactoring (e.g splitting out the
exclusive locking code into a common utility).
Hopefully the Windows support is fixed now.
Patch by Rainer Orth!
Differential Revision: https://reviews.llvm.org/D40944
llvm-svn: 320731
This includes a few nice bits of refactoring (e.g splitting out the
exclusive locking code into a common utility).
Patch by Rainer Orth!
Differential Revision: https://reviews.llvm.org/D40944
llvm-svn: 320726